yubihsm-shell-2.6.0/0000755000175100001770000000000014666530044013661 5ustar runnerdockeryubihsm-shell-2.6.0/CMakeLists.txt0000644000175100001770000002206414666527773016444 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # cmake_minimum_required (VERSION 3.5) # policy CMP0025 is to get AppleClang identifier rather than Clang for both # this matters since the apple compiler accepts different flags. cmake_policy(SET CMP0025 NEW) cmake_policy(SET CMP0042 NEW) cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0091 NEW) project (yubihsm-shell) option(BUILD_ONLY_LIB "Library only build" OFF) option(SUPRESS_MSVC_WARNINGS "Suppresses a lot of the warnings when compiling with MSVC" ON) include(${CMAKE_SOURCE_DIR}/cmake/SecurityFlags.cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") # Set various install paths if (NOT DEFINED YUBIHSM_INSTALL_LIB_DIR) set(YUBIHSM_INSTALL_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "Installation directory for libraries") endif () if (NOT DEFINED YUBIHSM_INSTALL_INC_DIR) set(YUBIHSM_INSTALL_INC_DIR "${CMAKE_INSTALL_PREFIX}/include" CACHE PATH "Installation directory for headers") endif () if (NOT DEFINED YUBIHSM_INSTALL_BIN_DIR) set(YUBIHSM_INSTALL_BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Installation directory for executables") endif () if (NOT DEFINED YUBIHSM_INSTALL_MAN_DIR) set(YUBIHSM_INSTALL_MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man" CACHE PATH "Installation directory for manual pages") endif () if (NOT DEFINED YUBIHSM_INSTALL_PKGCONFIG_DIR) set(YUBIHSM_INSTALL_PKGCONFIG_DIR "${CMAKE_INSTALL_PREFIX}/share/pkgconfig" CACHE PATH "Installation directory for pkgconfig (.pc) files") endif () if (NOT CMAKE_BUILD_TYPE) if (${RELEASE_BUILD} MATCHES 1) set (CMAKE_BUILD_TYPE Release) else () set (CMAKE_BUILD_TYPE Debug) endif () endif () if(MSVC) set(DISABLE_LTO 1) endif() if (NOT DISABLE_LTO) if (CMAKE_C_COMPILER_ID STREQUAL GNU) if (CMAKE_C_COMPILER_VERSION VERSION_GREATER 6.0) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto") endif () else () if (CMAKE_C_COMPILER_VERSION VERSION_GREATER 7.0) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto") endif () endif () endif () if (CMAKE_C_COMPILER_ID STREQUAL AppleClang) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-nullability-completeness -Wno-nullability-extension -Wno-expansion-to-defined -Wno-undef-prefix -Wno-extra-semi") elseif (NOT MSVC) set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-missing-braces -Wno-missing-field-initializers") # -Wl,--strip-all is dependent on linker not compiler... set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} -Wl,--strip-all") endif () if (CMAKE_MAJOR_VERSION LESS 3) if (CMAKE_C_COMPILER_ID STREQUAL GNU) # The C_STANDARD property was introduced in cmake 3.1 # https://cmake.org/cmake/help/latest/prop_tgt/C_STANDARD.html set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu11") endif () else () set (CMAKE_C_STANDARD 11) endif () set (yubihsm_shell_VERSION_MAJOR 2) set (yubihsm_shell_VERSION_MINOR 6) set (yubihsm_shell_VERSION_PATCH 0) set (VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(ENV{PKG_CONFIG_PATH} "/usr/libdata/pkgconfig:$ENV{PKG_CONFIG_PATH}") endif () if (NOT DEFINED DEFAULT_CONNECTOR_URL) set (DEFAULT_CONNECTOR_URL "http://localhost:12345") endif() add_definitions(-DDEFAULT_CONNECTOR_URL="${DEFAULT_CONNECTOR_URL}") enable_testing() find_package(codecov) add_definitions(-DOPENSSL_API_COMPAT=0x10000000L) if(WIN32) add_definitions(-DWIN32_LEAN_AND_MEAN=1) set(_WIN32 1) set(__WIN32 1) set(_WIN32_BCRYPT 1) endif() if(MSVC) message("win32") set(_MSVC 1) if(SUPRESS_MSVC_WARNINGS) set(MSVC_DISABLED_WARNINGS_LIST "C4706" # assignment within conditional expression; "C4996" # The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name "C4005" # redefinition of micros. Status codes are defined in winnt.h and then redefined in ntstatus.h with the same values "C4244" # conversion of size_t to other types. Since we don't have sizes that occupy more than 2 bytes, this should be safe to ignore "C4267" # conversion of size_t to other types. Since we don't have sizes that occupy more than 2 bytes, this should be safe to ignore "C4100" # unreferenced formal parameter "C4201" # nonstandard extension used: nameless struct/union "C4295" # array is too small to include a terminating null character. They arrays it's complaining about aren't meant to include terminating null character (triggered in tests and examples only) "C4127" # conditional expression is constant "C5105" # macro expansion producing 'defined' has undefined behavior "C4018" # signed/unsigned mismatch ) # The construction in the following 3 lines was taken from LibreSSL's # CMakeLists.txt. string(REPLACE "C" " -wd" MSVC_DISABLED_WARNINGS_STR ${MSVC_DISABLED_WARNINGS_LIST}) string(REGEX REPLACE "[/-]W[1234][ ]?" "" CMAKE_C_FLAGS ${CMAKE_C_FLAGS}) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -MP -W4 ${MSVC_DISABLED_WARNINGS_STR}") endif(SUPRESS_MSVC_WARNINGS) set (WITHOUT_MANPAGES 1) if (NOT WITHOUT_WIN32_BCRYPT) set (WIN32_BCRYPT 1) endif() else() message(STATUS "not win32") include(CheckFunctionExists) check_function_exists(memset_s HAVE_MEMSET_S) if (HAVE_MEMSET_S) add_definitions (-DHAVE_MEMSET_S) endif() check_function_exists(explicit_bzero HAVE_EXPLICIT_BZERO) if (HAVE_EXPLICIT_BZERO) add_definitions (-DHAVE_EXPLICIT_BZERO) endif () find_package (PkgConfig REQUIRED) if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") if (NOT LIBCRYPTO_LDFLAGS) set (LIBCRYPTO_LDFLAGS "-lcrypto") endif() if (NOT LIBCRYPTO_VERSION) set (LIBCRYPTO_VERSION "1.1.1") endif() else() include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() endif() if(NOT BUILD_ONLY_LIB) if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set (LIBEDIT_LDFLAGS "-ledit") else() pkg_search_module (LIBEDIT REQUIRED libedit) endif() endif() pkg_search_module (LIBCURL REQUIRED libcurl) pkg_search_module (LIBUSB REQUIRED libusb-1.0) endif() message("LIBCRYPTO_VERSION: ${LIBCRYPTO_VERSION}") add_subdirectory (lib) if(NOT BUILD_ONLY_LIB) add_subdirectory (pkcs11) if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") pkg_search_module (LIBPCSC REQUIRED libpcsclite) elseif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set (LIBPCSC_LDFLAGS "winscard.lib") elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") set(LIBPCSC_LDFLAGS "-Wl,-framework -Wl,PCSC") endif() add_subdirectory (ykhsmauth) add_subdirectory (yubihsm-auth) add_subdirectory (src) add_subdirectory (examples) add_subdirectory(yhwrap) endif() add_custom_target ( cppcheck COMMENT "Running cppcheck" COMMAND cppcheck --enable=warning,style,unusedFunction,missingInclude --template="[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)" -i ${CMAKE_SOURCE_DIR}/src/cmdline.c -i ${CMAKE_SOURCE_DIR}/pkcs11/cmdline.c --verbose --quiet ${CMAKE_SOURCE_DIR}/lib ${CMAKE_SOURCE_DIR}/src ${CMAKE_SOURCE_DIR}/pkcs11 ) set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}) add_custom_target ( dist COMMAND git archive --prefix=${ARCHIVE_NAME}/ HEAD | gzip > ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.gz WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) coverage_evaluate() message("Build summary:") message("") message(" Project name: ${CMAKE_PROJECT_NAME}") message(" Version: ${VERSION}") message(" Host type: ${CMAKE_SYSTEM_NAME}") message(" Path prefix: ${CMAKE_PREFIX_PATH}") message(" Compiler: ${CMAKE_C_COMPILER}") message(" Compiler ID: ${CMAKE_C_COMPILER_ID}") message(" Compiler version: ${CMAKE_C_COMPILER_VERSION}") message(" CMake version: ${CMAKE_VERSION}") message(" CFLAGS: ${CMAKE_C_FLAGS}") message(" CPPFLAGS: ${CMAKE_CXX_FLAGS}") message(" Warnings: ${WARN_FLAGS}") message(" Build type: ${CMAKE_BUILD_TYPE}") message("") message(" Install prefix: ${CMAKE_INSTALL_PREFIX}") message(" Install targets") message(" Libraries ${YUBIHSM_INSTALL_LIB_DIR}") message(" Includes ${YUBIHSM_INSTALL_INC_DIR}") message(" Binaries ${YUBIHSM_INSTALL_BIN_DIR}") message(" Manuals ${YUBIHSM_INSTALL_MAN_DIR}") message(" Pkg-config ${YUBIHSM_INSTALL_PKGCONFIG_DIR}") yubihsm-shell-2.6.0/LICENSE0000644000175100001770000002205614666527773014712 0ustar runnerdockerApache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: You must give any other recipients of the Work or Derivative Works a copy of this License; and You must cause any modified files to carry prominent notices stating that You changed the files; and You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS yubihsm-shell-2.6.0/cmake/0000755000175100001770000000000014666527773014760 5ustar runnerdockeryubihsm-shell-2.6.0/cmake/FindGcov.cmake0000644000175100001770000001173614666527773017471 0ustar runnerdocker# This file is part of CMake-codecov. # # Copyright (c) # 2015-2017 RWTH Aachen University, Federal Republic of Germany # # See the LICENSE file in the package base directory for details # # Written by Alexander Haase, alexander.haase@rwth-aachen.de # # include required Modules include(FindPackageHandleStandardArgs) # Search for gcov binary. set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY}) get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) foreach (LANG ${ENABLED_LANGUAGES}) # Gcov evaluation is dependend on the used compiler. Check gcov support for # each compiler that is used. If gcov binary was already found for this # compiler, do not try to find it again. if (NOT GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN) get_filename_component(COMPILER_PATH "${CMAKE_${LANG}_COMPILER}" PATH) if ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "GNU") # Some distributions like OSX (homebrew) ship gcov with the compiler # version appended as gcov-x. To find this binary we'll build the # suggested binary name with the compiler version. string(REGEX MATCH "^[0-9]+" GCC_VERSION "${CMAKE_${LANG}_COMPILER_VERSION}") find_program(GCOV_BIN NAMES gcov-${GCC_VERSION} gcov HINTS ${COMPILER_PATH}) elseif ("${CMAKE_${LANG}_COMPILER_ID}" STREQUAL "Clang") # Some distributions like Debian ship llvm-cov with the compiler # version appended as llvm-cov-x.y. To find this binary we'll build # the suggested binary name with the compiler version. string(REGEX MATCH "^[0-9]+.[0-9]+" LLVM_VERSION "${CMAKE_${LANG}_COMPILER_VERSION}") # llvm-cov prior version 3.5 seems to be not working with coverage # evaluation tools, but these versions are compatible with the gcc # gcov tool. if(LLVM_VERSION VERSION_GREATER 3.4) find_program(LLVM_COV_BIN NAMES "llvm-cov-${LLVM_VERSION}" "llvm-cov" HINTS ${COMPILER_PATH}) mark_as_advanced(LLVM_COV_BIN) if (LLVM_COV_BIN) find_program(LLVM_COV_WRAPPER "llvm-cov-wrapper" PATHS ${CMAKE_MODULE_PATH}) if (LLVM_COV_WRAPPER) set(GCOV_BIN "${LLVM_COV_WRAPPER}" CACHE FILEPATH "") # set additional parameters set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV "LLVM_COV_BIN=${LLVM_COV_BIN}" CACHE STRING "Environment variables for llvm-cov-wrapper.") mark_as_advanced(GCOV_${CMAKE_${LANG}_COMPILER_ID}_ENV) endif () endif () endif () if (NOT GCOV_BIN) # Fall back to gcov binary if llvm-cov was not found or is # incompatible. This is the default on OSX, but may crash on # recent Linux versions. find_program(GCOV_BIN gcov HINTS ${COMPILER_PATH}) endif () endif () if (GCOV_BIN) set(GCOV_${CMAKE_${LANG}_COMPILER_ID}_BIN "${GCOV_BIN}" CACHE STRING "${LANG} gcov binary.") if (NOT CMAKE_REQUIRED_QUIET) message("-- Found gcov evaluation for " "${CMAKE_${LANG}_COMPILER_ID}: ${GCOV_BIN}") endif() unset(GCOV_BIN CACHE) endif () endif () endforeach () # Add a new global target for all gcov targets. This target could be used to # generate the gcov files for the whole project instead of calling -gcov # for each target. if (NOT TARGET gcov) add_custom_target(gcov) endif (NOT TARGET gcov) # This function will add gcov evaluation for target . Only sources of # this target will be evaluated and no dependencies will be added. It will call # Gcov on any source file of once and store the gcov file in the same # directory. function (add_gcov_target TNAME) set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir) # We don't have to check, if the target has support for coverage, thus this # will be checked by add_coverage_target in Findcoverage.cmake. Instead we # have to determine which gcov binary to use. get_target_property(TSOURCES ${TNAME} SOURCES) set(SOURCES "") set(TCOMPILER "") foreach (FILE ${TSOURCES}) codecov_path_of_source(${FILE} FILE) if (NOT "${FILE}" STREQUAL "") codecov_lang_of_source(${FILE} LANG) if (NOT "${LANG}" STREQUAL "") list(APPEND SOURCES "${FILE}") set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID}) endif () endif () endforeach () # If no gcov binary was found, coverage data can't be evaluated. if (NOT GCOV_${TCOMPILER}_BIN) message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.") return() endif () set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}") set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}") set(BUFFER "") foreach(FILE ${SOURCES}) get_filename_component(FILE_PATH "${TDIR}/${FILE}" PATH) # call gcov add_custom_command(OUTPUT ${TDIR}/${FILE}.gcov COMMAND ${GCOV_ENV} ${GCOV_BIN} ${TDIR}/${FILE}.gcno > /dev/null DEPENDS ${TNAME} ${TDIR}/${FILE}.gcno WORKING_DIRECTORY ${FILE_PATH} ) list(APPEND BUFFER ${TDIR}/${FILE}.gcov) endforeach() # add target for gcov evaluation of add_custom_target(${TNAME}-gcov DEPENDS ${BUFFER}) # add evaluation target to the global gcov target. add_dependencies(gcov ${TNAME}-gcov) endfunction (add_gcov_target) yubihsm-shell-2.6.0/cmake/SecurityFlags.cmake0000644000175100001770000000457414666527773020560 0ustar runnerdockerinclude(CheckCCompilerFlag) if (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_C_COMPILER_ID STREQUAL "GNU") add_compile_options (-Wall -Wextra -Werror) add_compile_options (-Wformat -Wformat-nonliteral -Wformat-security) add_compile_options (-Wshadow) #add_compile_options (-Wcast-qual) add_compile_options (-Wmissing-prototypes) add_compile_options (-Wbad-function-cast) add_compile_options (-pedantic -pedantic-errors) add_compile_options (-fpie -fpic) if (NOT FUZZ) add_compile_options(-O2) add_definitions (-D_FORTIFY_SOURCE=2) endif () check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL) if (HAVE_STACK_PROTECTOR_ALL) message(STATUS "-fstack-protector-all support detected") add_compile_options(-fstack-protector-all) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fstack-protector-all") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fstack-protector-all") else () check_c_compiler_flag("-fstack-protector" HAVE_STACK_PROTECTOR) if(HAVE_STACK_PROTECTOR) message(STATUS "-fstack-protector support detected") add_compile_options(-fstack-protector) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fstack-protector") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fstack-protector") else () message(WARNING "No stack protection supported.") endif () endif () check_c_compiler_flag("-Wno-implicit-fallthrough" HAVE_NO_IMPLICIT_FALLTHROUGH) if (HAVE_NO_IMPLICIT_FALLTHROUGH) add_compile_options (-Wno-implicit-fallthrough) endif () if (NOT APPLE) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pie") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pie") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,noexecstack -Wl,-z,relro,-z,now") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,noexecstack -Wl,-z,relro,-z,now") endif() elseif (CMAKE_C_COMPILER_ID STREQUAL "MSVC") add_compile_options (/GS) add_compile_options (/Gs) add_link_options (/NXCOMPAT) add_link_options (/guard:cf) else () message(WARNING "Security related flags cannot be set for unknown C compiler.") endif () yubihsm-shell-2.6.0/cmake/gengetopt.cmake0000644000175100001770000000153514666527773017762 0ustar runnerdockermacro (find_gengetopt) if (NOT GENGETOPT_EXECUTABLE) find_program (GENGETOPT_EXECUTABLE gengetopt) if (NOT GENGETOPT_EXECUTABLE) message (FATAL_ERROR "gengetopt not found. Aborting...") endif () endif () endmacro () macro (add_gengetopt_files _basename) find_gengetopt () set (_ggo_extra_input ${ARGV}) set (_ggo_c ${CMAKE_CURRENT_SOURCE_DIR}/${_basename}.c) set (_ggo_h ${CMAKE_CURRENT_SOURCE_DIR}/${_basename}.h) set (_ggo_g ${CMAKE_CURRENT_SOURCE_DIR}/${_basename}.ggo) add_custom_command ( OUTPUT ${_ggo_c} ${_ggo_h} COMMAND gengetopt ${_ggo_extra_input} -i ${_ggo_g} --output-dir ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS ${_ggo_g} # BYPRODUCTS COMMENT "Generating getopt parser code (cmdline.{h,c}) ..." VERBATIM ) set (GGO_C ${_ggo_c}) set (GGO_H ${_ggo_h}) endmacro (add_gengetopt_files) yubihsm-shell-2.6.0/cmake/FindLcov.cmake0000644000175100001770000003005014666527773017464 0ustar runnerdocker# This file is part of CMake-codecov. # # Copyright (c) # 2015-2017 RWTH Aachen University, Federal Republic of Germany # # See the LICENSE file in the package base directory for details # # Written by Alexander Haase, alexander.haase@rwth-aachen.de # # configuration set(LCOV_DATA_PATH "${CMAKE_BINARY_DIR}/lcov/data") set(LCOV_DATA_PATH_INIT "${LCOV_DATA_PATH}/init") set(LCOV_DATA_PATH_CAPTURE "${LCOV_DATA_PATH}/capture") set(LCOV_HTML_PATH "${CMAKE_BINARY_DIR}/lcov/html") # Search for Gcov which is used by Lcov. find_package(Gcov) # This function will add lcov evaluation for target . Only sources of # this target will be evaluated and no dependencies will be added. It will call # geninfo on any source file of once and store the info file in the same # directory. # # Note: This function is only a wrapper to define this function always, even if # coverage is not supported by the compiler or disabled. This function must # be defined here, because the module will be exited, if there is no coverage # support by the compiler or it is disabled by the user. function (add_lcov_target TNAME) if (LCOV_FOUND) # capture initial coverage data lcov_capture_initial_tgt(${TNAME}) # capture coverage data after execution lcov_capture_tgt(${TNAME}) endif () endfunction (add_lcov_target) # include required Modules include(FindPackageHandleStandardArgs) # Search for required lcov binaries. find_program(LCOV_BIN lcov) find_program(GENINFO_BIN geninfo) find_program(GENHTML_BIN genhtml) find_package_handle_standard_args(lcov REQUIRED_VARS LCOV_BIN GENINFO_BIN GENHTML_BIN ) # enable genhtml C++ demangeling, if c++filt is found. set(GENHTML_CPPFILT_FLAG "") find_program(CPPFILT_BIN c++filt) if (NOT CPPFILT_BIN STREQUAL "") set(GENHTML_CPPFILT_FLAG "--demangle-cpp") endif (NOT CPPFILT_BIN STREQUAL "") # enable no-external flag for lcov, if available. if (GENINFO_BIN AND NOT DEFINED GENINFO_EXTERN_FLAG) set(FLAG "") execute_process(COMMAND ${GENINFO_BIN} --help OUTPUT_VARIABLE GENINFO_HELP) string(REGEX MATCH "external" GENINFO_RES "${GENINFO_HELP}") if (GENINFO_RES) set(FLAG "--no-external") endif () set(GENINFO_EXTERN_FLAG "${FLAG}" CACHE STRING "Geninfo flag to exclude system sources.") endif () # If Lcov was not found, exit module now. if (NOT LCOV_FOUND) return() endif (NOT LCOV_FOUND) # Create directories to be used. file(MAKE_DIRECTORY ${LCOV_DATA_PATH_INIT}) file(MAKE_DIRECTORY ${LCOV_DATA_PATH_CAPTURE}) set(LCOV_REMOVE_PATTERNS "") # This function will merge lcov files to a single target file. Additional lcov # flags may be set with setting LCOV_EXTRA_FLAGS before calling this function. function (lcov_merge_files OUTFILE ...) # Remove ${OUTFILE} from ${ARGV} and generate lcov parameters with files. list(REMOVE_AT ARGV 0) # Generate merged file. string(REPLACE "${CMAKE_BINARY_DIR}/" "" FILE_REL "${OUTFILE}") add_custom_command(OUTPUT "${OUTFILE}.raw" COMMAND cat ${ARGV} > ${OUTFILE}.raw DEPENDS ${ARGV} COMMENT "Generating ${FILE_REL}" ) add_custom_command(OUTPUT "${OUTFILE}" COMMAND ${LCOV_BIN} --quiet -a ${OUTFILE}.raw --output-file ${OUTFILE} --base-directory ${PROJECT_SOURCE_DIR} ${LCOV_EXTRA_FLAGS} COMMAND ${LCOV_BIN} --quiet -r ${OUTFILE} ${LCOV_REMOVE_PATTERNS} --output-file ${OUTFILE} ${LCOV_EXTRA_FLAGS} DEPENDS ${OUTFILE}.raw COMMENT "Post-processing ${FILE_REL}" ) endfunction () # Add a new global target to generate initial coverage reports for all targets. # This target will be used to generate the global initial info file, which is # used to gather even empty report data. if (NOT TARGET lcov-capture-init) add_custom_target(lcov-capture-init) set(LCOV_CAPTURE_INIT_FILES "" CACHE INTERNAL "") endif (NOT TARGET lcov-capture-init) # This function will add initial capture of coverage data for target , # which is needed to get also data for objects, which were not loaded at # execution time. It will call geninfo for every source file of once and # store the info file in the same directory. function (lcov_capture_initial_tgt TNAME) # We don't have to check, if the target has support for coverage, thus this # will be checked by add_coverage_target in Findcoverage.cmake. Instead we # have to determine which gcov binary to use. get_target_property(TSOURCES ${TNAME} SOURCES) set(SOURCES "") set(TCOMPILER "") foreach (FILE ${TSOURCES}) codecov_path_of_source(${FILE} FILE) if (NOT "${FILE}" STREQUAL "") codecov_lang_of_source(${FILE} LANG) if (NOT "${LANG}" STREQUAL "") list(APPEND SOURCES "${FILE}") set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID}) endif () endif () endforeach () # If no gcov binary was found, coverage data can't be evaluated. if (NOT GCOV_${TCOMPILER}_BIN) message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.") return() endif () set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}") set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}") set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir) set(GENINFO_FILES "") foreach(FILE ${SOURCES}) # generate empty coverage files set(OUTFILE "${TDIR}/${FILE}.info.init") list(APPEND GENINFO_FILES ${OUTFILE}) add_custom_command(OUTPUT ${OUTFILE} COMMAND ${GCOV_ENV} ${GENINFO_BIN} --quiet --base-directory ${PROJECT_SOURCE_DIR} --initial --gcov-tool ${GCOV_BIN} --output-filename ${OUTFILE} ${GENINFO_EXTERN_FLAG} ${TDIR}/${FILE}.gcno DEPENDS ${TNAME} COMMENT "Capturing initial coverage data for ${FILE}" ) endforeach() # Concatenate all files generated by geninfo to a single file per target. set(OUTFILE "${LCOV_DATA_PATH_INIT}/${TNAME}.info") set(LCOV_EXTRA_FLAGS "--initial") lcov_merge_files("${OUTFILE}" ${GENINFO_FILES}) add_custom_target(${TNAME}-capture-init ALL DEPENDS ${OUTFILE}) # add geninfo file generation to global lcov-geninfo target add_dependencies(lcov-capture-init ${TNAME}-capture-init) set(LCOV_CAPTURE_INIT_FILES "${LCOV_CAPTURE_INIT_FILES}" "${OUTFILE}" CACHE INTERNAL "" ) endfunction (lcov_capture_initial_tgt) # This function will generate the global info file for all targets. It has to be # called after all other CMake functions in the root CMakeLists.txt file, to get # a full list of all targets that generate coverage data. function (lcov_capture_initial) # Skip this function (and do not create the following targets), if there are # no input files. if ("${LCOV_CAPTURE_INIT_FILES}" STREQUAL "") return() endif () # Add a new target to merge the files of all targets. set(OUTFILE "${LCOV_DATA_PATH_INIT}/all_targets.info") lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_INIT_FILES}) add_custom_target(lcov-geninfo-init ALL DEPENDS ${OUTFILE} lcov-capture-init ) endfunction (lcov_capture_initial) # Add a new global target to generate coverage reports for all targets. This # target will be used to generate the global info file. if (NOT TARGET lcov-capture) add_custom_target(lcov-capture) set(LCOV_CAPTURE_FILES "" CACHE INTERNAL "") endif (NOT TARGET lcov-capture) # This function will add capture of coverage data for target , which is # needed to get also data for objects, which were not loaded at execution time. # It will call geninfo for every source file of once and store the info # file in the same directory. function (lcov_capture_tgt TNAME) # We don't have to check, if the target has support for coverage, thus this # will be checked by add_coverage_target in Findcoverage.cmake. Instead we # have to determine which gcov binary to use. get_target_property(TSOURCES ${TNAME} SOURCES) set(SOURCES "") set(TCOMPILER "") foreach (FILE ${TSOURCES}) codecov_path_of_source(${FILE} FILE) if (NOT "${FILE}" STREQUAL "") codecov_lang_of_source(${FILE} LANG) if (NOT "${LANG}" STREQUAL "") list(APPEND SOURCES "${FILE}") set(TCOMPILER ${CMAKE_${LANG}_COMPILER_ID}) endif () endif () endforeach () # If no gcov binary was found, coverage data can't be evaluated. if (NOT GCOV_${TCOMPILER}_BIN) message(WARNING "No coverage evaluation binary found for ${TCOMPILER}.") return() endif () set(GCOV_BIN "${GCOV_${TCOMPILER}_BIN}") set(GCOV_ENV "${GCOV_${TCOMPILER}_ENV}") set(TDIR ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${TNAME}.dir) set(GENINFO_FILES "") foreach(FILE ${SOURCES}) # Generate coverage files. If no .gcda file was generated during # execution, the empty coverage file will be used instead. set(OUTFILE "${TDIR}/${FILE}.info") list(APPEND GENINFO_FILES ${OUTFILE}) add_custom_command(OUTPUT ${OUTFILE} COMMAND test -f "${TDIR}/${FILE}.gcda" && ${GCOV_ENV} ${GENINFO_BIN} --quiet --base-directory ${PROJECT_SOURCE_DIR} --gcov-tool ${GCOV_BIN} --output-filename ${OUTFILE} ${GENINFO_EXTERN_FLAG} ${TDIR}/${FILE}.gcda || cp ${OUTFILE}.init ${OUTFILE} DEPENDS ${TNAME} ${TNAME}-capture-init COMMENT "Capturing coverage data for ${FILE}" ) endforeach() # Concatenate all files generated by geninfo to a single file per target. set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/${TNAME}.info") lcov_merge_files("${OUTFILE}" ${GENINFO_FILES}) add_custom_target(${TNAME}-geninfo DEPENDS ${OUTFILE}) # add geninfo file generation to global lcov-capture target add_dependencies(lcov-capture ${TNAME}-geninfo) set(LCOV_CAPTURE_FILES "${LCOV_CAPTURE_FILES}" "${OUTFILE}" CACHE INTERNAL "" ) # Add target for generating html output for this target only. file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/${TNAME}) add_custom_target(${TNAME}-genhtml COMMAND ${GENHTML_BIN} --quiet --sort --prefix ${PROJECT_SOURCE_DIR} --baseline-file ${LCOV_DATA_PATH_INIT}/${TNAME}.info --output-directory ${LCOV_HTML_PATH}/${TNAME} --title "${CMAKE_PROJECT_NAME} - target ${TNAME}" ${GENHTML_CPPFILT_FLAG} ${OUTFILE} DEPENDS ${TNAME}-geninfo ${TNAME}-capture-init ) endfunction (lcov_capture_tgt) # This function will generate the global info file for all targets. It has to be # called after all other CMake functions in the root CMakeLists.txt file, to get # a full list of all targets that generate coverage data. function (lcov_capture) # Skip this function (and do not create the following targets), if there are # no input files. if ("${LCOV_CAPTURE_FILES}" STREQUAL "") return() endif () # Add a new target to merge the files of all targets. set(OUTFILE "${LCOV_DATA_PATH_CAPTURE}/all_targets.info") lcov_merge_files("${OUTFILE}" ${LCOV_CAPTURE_FILES}) add_custom_target(lcov-geninfo DEPENDS ${OUTFILE} lcov-capture) # Add a new global target for all lcov targets. This target could be used to # generate the lcov html output for the whole project instead of calling # -geninfo and -genhtml for each target. It will also be # used to generate a html site for all project data together instead of one # for each target. if (NOT TARGET lcov) file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/all_targets) add_custom_target(lcov COMMAND ${GENHTML_BIN} --quiet --sort --baseline-file ${LCOV_DATA_PATH_INIT}/all_targets.info --output-directory ${LCOV_HTML_PATH}/all_targets --title "${CMAKE_PROJECT_NAME}" --prefix "${PROJECT_SOURCE_DIR}" ${GENHTML_CPPFILT_FLAG} ${OUTFILE} DEPENDS lcov-geninfo-init lcov-geninfo ) endif () endfunction (lcov_capture) # Add a new global target to generate the lcov html report for the whole project # instead of calling -genhtml for each target (to create an own report # for each target). Instead of the lcov target it does not require geninfo for # all targets, so you have to call -geninfo to generate the info files # the targets you'd like to have in your report or lcov-geninfo for generating # info files for all targets before calling lcov-genhtml. file(MAKE_DIRECTORY ${LCOV_HTML_PATH}/selected_targets) if (NOT TARGET lcov-genhtml) add_custom_target(lcov-genhtml COMMAND ${GENHTML_BIN} --quiet --output-directory ${LCOV_HTML_PATH}/selected_targets --title \"${CMAKE_PROJECT_NAME} - targets `find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name \"all_targets.info\" -exec basename {} .info \\\;`\" --prefix ${PROJECT_SOURCE_DIR} --sort ${GENHTML_CPPFILT_FLAG} `find ${LCOV_DATA_PATH_CAPTURE} -name \"*.info\" ! -name \"all_targets.info\"` ) endif (NOT TARGET lcov-genhtml) yubihsm-shell-2.6.0/cmake/openssl.cmake0000644000175100001770000000065314666527773017451 0ustar runnerdockermacro (find_libcrypto) if(NOT LIBCRYPTO_LDFLAGS) if(WIN32) find_package(OpenSSL REQUIRED) set(LIBCRYPTO_LDFLAGS "OpenSSL::Crypto") set(LIBCRYPTO_VERSION ${OPENSSL_VERSION}) set(LIBCRYPTO_INCLUDEDIR ${OPENSSL_INCLUDE_DIR}) else(WIN32) pkg_search_module (LIBCRYPTO REQUIRED libcrypto) endif(WIN32) endif(NOT LIBCRYPTO_LDFLAGS) endmacro()yubihsm-shell-2.6.0/cmake/mingw32.cmake0000644000175100001770000000117314666527773017252 0ustar runnerdocker# the name of the target operating system SET(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32 ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) yubihsm-shell-2.6.0/cmake/getopt.cmake0000644000175100001770000000101314666527773017257 0ustar runnerdockermacro (find_getopt) if (MSVC) if(NOT GETOPT_LIB_DIR AND NOT GETOPT_INCLUDE_DIR) message (FATAL_ERROR "Missing 'GETOPT_LIB_DIR' and 'GETOPT_INCLUDE_DIR' options to CMake command. Aborting...") else(NOT GETOPT_LIB_DIR AND NOT GETOPT_INCLUDE_DIR) find_library(GETOPT getopt PATHS ${GETOPT_LIB_DIR}) set(GETOPT_LIBS ${GETOPT}) include_directories(${GETOPT_INCLUDE_DIR}) endif(NOT GETOPT_LIB_DIR AND NOT GETOPT_INCLUDE_DIR) endif (MSVC) endmacro ()yubihsm-shell-2.6.0/cmake/Findcodecov.cmake0000644000175100001770000002034314666527773020207 0ustar runnerdocker# This file is part of CMake-codecov. # # Copyright (c) # 2015-2017 RWTH Aachen University, Federal Republic of Germany # # See the LICENSE file in the package base directory for details # # Written by Alexander Haase, alexander.haase@rwth-aachen.de # # Add an option to choose, if coverage should be enabled or not. If enabled # marked targets will be build with coverage support and appropriate targets # will be added. If disabled coverage will be ignored for *ALL* targets. option(ENABLE_COVERAGE "Enable coverage build." OFF) set(COVERAGE_FLAG_CANDIDATES # gcc and clang "-O0 -g -fprofile-arcs -ftest-coverage" # gcc and clang fallback "-O0 -g --coverage" ) # Add coverage support for target ${TNAME} and register target for coverage # evaluation. If coverage is disabled or not supported, this function will # simply do nothing. # # Note: This function is only a wrapper to define this function always, even if # coverage is not supported by the compiler or disabled. This function must # be defined here, because the module will be exited, if there is no coverage # support by the compiler or it is disabled by the user. function (add_coverage TNAME) # only add coverage for target, if coverage is support and enabled. if (ENABLE_COVERAGE) foreach (TNAME ${ARGV}) add_coverage_target(${TNAME}) endforeach () endif () endfunction (add_coverage) # Add global target to gather coverage information after all targets have been # added. Other evaluation functions could be added here, after checks for the # specific module have been passed. # # Note: This function is only a wrapper to define this function always, even if # coverage is not supported by the compiler or disabled. This function must # be defined here, because the module will be exited, if there is no coverage # support by the compiler or it is disabled by the user. function (coverage_evaluate) # add lcov evaluation if (LCOV_FOUND) lcov_capture_initial() lcov_capture() endif (LCOV_FOUND) endfunction () # Exit this module, if coverage is disabled. add_coverage is defined before this # return, so this module can be exited now safely without breaking any build- # scripts. if (NOT ENABLE_COVERAGE) return() endif () # Find the reuired flags foreach language. set(CMAKE_REQUIRED_QUIET_SAVE ${CMAKE_REQUIRED_QUIET}) set(CMAKE_REQUIRED_QUIET ${codecov_FIND_QUIETLY}) get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) foreach (LANG ${ENABLED_LANGUAGES}) # Coverage flags are not dependend on language, but the used compiler. So # instead of searching flags foreach language, search flags foreach compiler # used. set(COMPILER ${CMAKE_${LANG}_COMPILER_ID}) if (NOT COVERAGE_${COMPILER}_FLAGS) foreach (FLAG ${COVERAGE_FLAG_CANDIDATES}) if(NOT CMAKE_REQUIRED_QUIET) message(STATUS "Try ${COMPILER} code coverage flag = [${FLAG}]") endif() set(CMAKE_REQUIRED_FLAGS "${FLAG}") unset(COVERAGE_FLAG_DETECTED CACHE) if (${LANG} STREQUAL "C") include(CheckCCompilerFlag) check_c_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED) elseif (${LANG} STREQUAL "CXX") include(CheckCXXCompilerFlag) check_cxx_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED) elseif (${LANG} STREQUAL "Fortran") # CheckFortranCompilerFlag was introduced in CMake 3.x. To be # compatible with older Cmake versions, we will check if this # module is present before we use it. Otherwise we will define # Fortran coverage support as not available. include(CheckFortranCompilerFlag OPTIONAL RESULT_VARIABLE INCLUDED) if (INCLUDED) check_fortran_compiler_flag("${FLAG}" COVERAGE_FLAG_DETECTED) elseif (NOT CMAKE_REQUIRED_QUIET) message("-- Performing Test COVERAGE_FLAG_DETECTED") message("-- Performing Test COVERAGE_FLAG_DETECTED - Failed" " (Check not supported)") endif () endif() if (COVERAGE_FLAG_DETECTED) set(COVERAGE_${COMPILER}_FLAGS "${FLAG}" CACHE STRING "${COMPILER} flags for code coverage.") mark_as_advanced(COVERAGE_${COMPILER}_FLAGS) break() else () message(WARNING "Code coverage is not available for ${COMPILER}" " compiler. Targets using this compiler will be " "compiled without it.") endif () endforeach () endif () endforeach () set(CMAKE_REQUIRED_QUIET ${CMAKE_REQUIRED_QUIET_SAVE}) # Helper function to get the language of a source file. function (codecov_lang_of_source FILE RETURN_VAR) get_filename_component(FILE_EXT "${FILE}" EXT) string(TOLOWER "${FILE_EXT}" FILE_EXT) string(SUBSTRING "${FILE_EXT}" 1 -1 FILE_EXT) get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES) foreach (LANG ${ENABLED_LANGUAGES}) list(FIND CMAKE_${LANG}_SOURCE_FILE_EXTENSIONS "${FILE_EXT}" TEMP) if (NOT ${TEMP} EQUAL -1) set(${RETURN_VAR} "${LANG}" PARENT_SCOPE) return() endif () endforeach() set(${RETURN_VAR} "" PARENT_SCOPE) endfunction () # Helper function to get the relative path of the source file destination path. # This path is needed by FindGcov and FindLcov cmake files to locate the # captured data. function (codecov_path_of_source FILE RETURN_VAR) string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _source ${FILE}) # If expression was found, SOURCEFILE is a generator-expression for an # object library. Currently we found no way to call this function automatic # for the referenced target, so it must be called in the directoryso of the # object library definition. if (NOT "${_source}" STREQUAL "") set(${RETURN_VAR} "" PARENT_SCOPE) return() endif () string(REPLACE "${CMAKE_CURRENT_BINARY_DIR}/" "" FILE "${FILE}") if(IS_ABSOLUTE ${FILE}) file(RELATIVE_PATH FILE ${CMAKE_CURRENT_SOURCE_DIR} ${FILE}) endif() # get the right path for file string(REPLACE ".." "__" PATH "${FILE}") set(${RETURN_VAR} "${PATH}" PARENT_SCOPE) endfunction() # Add coverage support for target ${TNAME} and register target for coverage # evaluation. function(add_coverage_target TNAME) # Check if all sources for target use the same compiler. If a target uses # e.g. C and Fortran mixed and uses different compilers (e.g. clang and # gfortran) this can trigger huge problems, because different compilers may # use different implementations for code coverage. get_target_property(TSOURCES ${TNAME} SOURCES) set(TARGET_COMPILER "") set(ADDITIONAL_FILES "") foreach (FILE ${TSOURCES}) # If expression was found, FILE is a generator-expression for an object # library. Object libraries will be ignored. string(REGEX MATCH "TARGET_OBJECTS:([^ >]+)" _file ${FILE}) if ("${_file}" STREQUAL "") codecov_lang_of_source(${FILE} LANG) if (LANG) list(APPEND TARGET_COMPILER ${CMAKE_${LANG}_COMPILER_ID}) list(APPEND ADDITIONAL_FILES "${FILE}.gcno") list(APPEND ADDITIONAL_FILES "${FILE}.gcda") endif () endif () endforeach () list(REMOVE_DUPLICATES TARGET_COMPILER) list(LENGTH TARGET_COMPILER NUM_COMPILERS) if (NUM_COMPILERS GREATER 1) message(WARNING "Can't use code coverage for target ${TNAME}, because " "it will be compiled by incompatible compilers. Target will be " "compiled without code coverage.") return() elseif (NUM_COMPILERS EQUAL 0) message(WARNING "Can't use code coverage for target ${TNAME}, because " "it uses an unknown compiler. Target will be compiled without " "code coverage.") return() elseif (NOT DEFINED "COVERAGE_${TARGET_COMPILER}_FLAGS") # A warning has been printed before, so just return if flags for this # compiler aren't available. return() endif() # enable coverage for target set_property(TARGET ${TNAME} APPEND_STRING PROPERTY COMPILE_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}") set_property(TARGET ${TNAME} APPEND_STRING PROPERTY LINK_FLAGS " ${COVERAGE_${TARGET_COMPILER}_FLAGS}") # Add gcov files generated by compiler to clean target. set(CLEAN_FILES "") foreach (FILE ${ADDITIONAL_FILES}) codecov_path_of_source(${FILE} FILE) list(APPEND CLEAN_FILES "CMakeFiles/${TNAME}.dir/${FILE}") endforeach() set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEAN_FILES}") add_gcov_target(${TNAME}) add_lcov_target(${TNAME}) endfunction(add_coverage_target) # Include modules for parsing the collected data and output it in a readable # format (like gcov and lcov). find_package(Gcov) find_package(Lcov) yubihsm-shell-2.6.0/cmake/help2man.cmake0000644000175100001770000000066114666527773017473 0ustar runnerdockerfind_program (HELP2MAN_LOCATION help2man) IF (NOT HELP2MAN_LOCATION) message (FATAL_ERROR "Cannot find help2man. Please install it.") ENDIF () MACRO (add_help2man_manpage file command) add_custom_command (OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${file} COMMAND ${HELP2MAN_LOCATION} ARGS -s1 -N -o ${CMAKE_CURRENT_BINARY_DIR}/${file} ./${command} DEPENDS ${command} COMMENT "Building manpage for ${command}") ENDMACRO () yubihsm-shell-2.6.0/cmake/cppcheck.cmake0000644000175100001770000000265514666527773017552 0ustar runnerdockermacro (add_cppcheck_target _cc_target _cc_directories _cc_ignore) set(_cc_directories_var ${_cc_directories}) string (REPLACE " " " ${CMAKE_CURRENT_SOURCE_DIR}/" _cc_abs_directories ${_cc_directories_var}) set (_cc_abs_directories "${CMAKE_CURRENT_SOURCE_DIR}/${_cc_abs_directories}") separate_arguments (xxx UNIX_COMMAND "${_cc_abs_directories}") if (_cc_ignore STREQUAL "") string (REPLACE " " "${CMAKE_CURRENT_SOURCE_DIR}/" _cc_abs_ignore ${_cc_ignore}) set (_cc_abs_ignore ";${CMAKE_CURRENT_SOURCE_DIR}/${_cc_abs_ignore}") endif () set (_cc_extra_input "${ARGV3}") message ("Replaced ?${_cc_abs_directories}?") message ("Replaxxx ?${xxx}?") list (LENGTH _cc_abs_directories bla) message ("ignored ${_cc_abs_ignore} length is ${bla}") file(GLOB_RECURSE ALL_SOURCE_FILES *.c *.h) #message (${ALL_SOURCE_FILES}) # # set (_ignore_arg "--ignore ${_ignore}") #else () # set (_ignore_arg "set ${_ignore}") #endif () #list (APPEND _cpp_remove_list "") #list (APPEND _cpp_remove_list ) #set (_ggo_extra_input ${ARGV1}) add_custom_target ( ${_cc_target} COMMAND cppcheck --enable=all --template="[{severity}][{id}] {message} {callstack} \(On {file}:{line}\)" --suppress="unusedStructMember" -i="${_cc_abs_ignore}" --verbose --quiet ${_cc_extra_input} #"${_cc_abs_directories}" ${CMAKE_SOURCE_DIR} #"${xxx}" #VERBATIM ) endmacro(add_cppcheck_target) yubihsm-shell-2.6.0/cmake/mingw64.cmake0000644000175100001770000000120314666527773017251 0ustar runnerdocker# the name of the target operating system SET(CMAKE_SYSTEM_NAME Windows) # which compilers to use for C and C++ SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc) SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++) SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres) # here is the target environment located SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32 ) # adjust the default behaviour of the FIND_XXX() commands: # search headers and libraries in the target environment, search # programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) yubihsm-shell-2.6.0/aes_cmac/0000755000175100001770000000000014666527773015433 5ustar runnerdockeryubihsm-shell-2.6.0/aes_cmac/aes_cmac.h0000644000175100001770000000222614666527773017341 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "aes.h" typedef struct { aes_context *aes_ctx; uint8_t k1[AES_BLOCK_SIZE]; uint8_t k2[AES_BLOCK_SIZE]; } aes_cmac_context_t; #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif int YH_INTERNAL aes_cmac_init(aes_context *aes_ctx, aes_cmac_context_t *ctx); int YH_INTERNAL aes_cmac_encrypt(aes_cmac_context_t *ctx, const uint8_t *message, const uint16_t message_len, uint8_t *mac); void YH_INTERNAL aes_cmac_destroy(aes_cmac_context_t *ctx); yubihsm-shell-2.6.0/aes_cmac/aes.h0000644000175100001770000000441314666527773016356 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* aes.h ** ** Defines the AES crypto module for CMAC */ #ifndef _AESCMAC_AES_H_ #define _AESCMAC_AES_H_ #include #include "../common/platform-config.h" #ifdef _WIN32_BCRYPT #include #include #include #else #include #endif #ifndef AES_BLOCK_SIZE // Defined in openssl/aes.h #define AES_BLOCK_SIZE 16 #endif #ifdef __cplusplus extern "C" { #endif typedef struct { #ifdef _WIN32_BCRYPT BCRYPT_ALG_HANDLE hAlgCBC; BCRYPT_ALG_HANDLE hAlgECB; BCRYPT_KEY_HANDLE hKeyCBC; BCRYPT_KEY_HANDLE hKeyECB; PBYTE pbKeyCBCObj; PBYTE pbKeyECBObj; size_t cbKeyObj; #else EVP_CIPHER_CTX *ctx; uint16_t key_len; uint8_t key[32]; #endif } aes_context; #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif int YH_INTERNAL aes_load_key(const char *key, aes_context *ctx); int YH_INTERNAL aes_set_key(const uint8_t *key, uint16_t key_len, aes_context *ctx); int YH_INTERNAL aes_encrypt(const uint8_t *in, uint8_t *out, aes_context *ctx); int YH_INTERNAL aes_decrypt(const uint8_t *in, uint8_t *out, aes_context *ctx); int YH_INTERNAL aes_cbc_encrypt(const uint8_t *in, uint8_t *out, uint16_t len, const uint8_t *iv, aes_context *ctx); int YH_INTERNAL aes_cbc_decrypt(const uint8_t *in, uint8_t *out, uint16_t len, const uint8_t *iv, aes_context *ctx); int YH_INTERNAL aes_add_padding(uint8_t *in, uint16_t max_len, uint16_t *len); void YH_INTERNAL aes_remove_padding(uint8_t *in, uint16_t *len); void YH_INTERNAL aes_destroy(aes_context *ctx); #ifdef __cplusplus } #endif #endif /* _AESCMAC_AES_H_ */ yubihsm-shell-2.6.0/aes_cmac/tests/0000755000175100001770000000000014666527773016575 5ustar runnerdockeryubihsm-shell-2.6.0/aes_cmac/tests/aes_cmac_tests.c0000644000175100001770000002161214666527773021720 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "../aes_cmac.h" #define asrt(c, e, m) _asrt(__LINE__, c, e, m); static void _asrt(int line, int check, int expected, unsigned char *msg) { if (check == expected) return; fprintf(stderr, "<%s>:%d check failed with value %d (0x%x), expected %d (0x%x)\n", msg, line, check, check, expected, expected); exit(EXIT_FAILURE); } int main() { aes_context aes = {0}; aes_cmac_context_t ctx = {0}; uint8_t mac[AES_BLOCK_SIZE]; uint8_t m[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10}; uint8_t k_128[] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c}; uint8_t k_192[] = {0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b}; uint8_t k_256[] = {0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4}; uint8_t mac1[] = {0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46}; uint8_t mac2[] = {0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c}; uint8_t mac3[] = {0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30, 0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27}; uint8_t mac4[] = {0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe}; uint8_t mac5[] = {0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67}; uint8_t mac6[] = {0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84}; uint8_t mac7[] = {0x8a, 0x1d, 0xe5, 0xbe, 0x2e, 0xb3, 0x1a, 0xad, 0x08, 0x9a, 0x82, 0xe6, 0xee, 0x90, 0x8b, 0x0e}; uint8_t mac8[] = {0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11}; uint8_t mac9[] = {0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83}; uint8_t mac10[] = {0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c}; uint8_t mac11[] = {0xaa, 0xf3, 0xd8, 0xf1, 0xde, 0x56, 0x40, 0xc2, 0x32, 0xf5, 0xb1, 0x69, 0xb9, 0xc9, 0x11, 0xe6}; uint8_t mac12[] = {0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10}; aes_set_key(k_128, sizeof(k_128), &aes); aes_cmac_init(&aes, &ctx); aes_cmac_encrypt(&ctx, m, 0, mac); asrt(memcmp(mac, mac1, 16), 0, (unsigned char *) "MAC1"); aes_cmac_encrypt(&ctx, m, 16, mac); asrt(memcmp(mac, mac2, 16), 0, (unsigned char *) "MAC2"); aes_cmac_encrypt(&ctx, m, 40, mac); asrt(memcmp(mac, mac3, 16), 0, (unsigned char *) "MAC3"); aes_cmac_encrypt(&ctx, m, 64, mac); asrt(memcmp(mac, mac4, 16), 0, (unsigned char *) "MAC4"); aes_cmac_destroy(&ctx); aes_destroy(&aes); aes_set_key(k_192, sizeof(k_192), &aes); aes_cmac_init(&aes, &ctx); aes_cmac_encrypt(&ctx, m, 0, mac); asrt(memcmp(mac, mac5, 16), 0, (unsigned char *) "MAC5"); aes_cmac_encrypt(&ctx, m, 16, mac); asrt(memcmp(mac, mac6, 16), 0, (unsigned char *) "MAC6"); aes_cmac_encrypt(&ctx, m, 40, mac); asrt(memcmp(mac, mac7, 16), 0, (unsigned char *) "MAC7"); aes_cmac_encrypt(&ctx, m, 64, mac); asrt(memcmp(mac, mac8, 16), 0, (unsigned char *) "MAC8"); aes_cmac_destroy(&ctx); aes_destroy(&aes); aes_set_key(k_256, sizeof(k_256), &aes); aes_cmac_init(&aes, &ctx); aes_cmac_encrypt(&ctx, m, 0, mac); asrt(memcmp(mac, mac9, 16), 0, (unsigned char *) "MAC9"); aes_cmac_encrypt(&ctx, m, 16, mac); asrt(memcmp(mac, mac10, 16), 0, (unsigned char *) "MAC10"); aes_cmac_encrypt(&ctx, m, 40, mac); asrt(memcmp(mac, mac11, 16), 0, (unsigned char *) "MAC11"); aes_cmac_encrypt(&ctx, m, 64, mac); asrt(memcmp(mac, mac12, 16), 0, (unsigned char *) "MAC12"); aes_cmac_destroy(&ctx); aes_destroy(&aes); // Padding tests uint8_t a[48]; uint16_t l; l = 3; memset(a, 0xab, 48); aes_add_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00", 16), 0, (unsigned char *) "PADDING 1a"); asrt(l, 16, (unsigned char *) "PADDING 1b"); aes_remove_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab", 3), 0, (unsigned char *) "PADDING 1c"); asrt(l, 3, (unsigned char *) "PADDING 1d"); fprintf(stderr, "\n"); l = 15; memset(a, 0xab, 48); aes_add_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\x80", 16), 0, (unsigned char *) "PADDING 2a"); asrt(l, 16, (unsigned char *) "PADDING 2b"); aes_remove_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab", 15), 0, (unsigned char *) "PADDING 2c"); asrt(l, 15, (unsigned char *) "PADDING 2d"); fprintf(stderr, "\n"); l = 16; memset(a, 0xab, 48); aes_add_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00", 32), 0, (unsigned char *) "PADDING 3a"); asrt(l, 32, (unsigned char *) "PADDING 3b"); aes_remove_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab", 16), 0, (unsigned char *) "PADDING 3c"); asrt(l, 16, (unsigned char *) "PADDING 3d"); fprintf(stderr, "\n"); l = 19; memset(a, 0xab, 48); aes_add_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab\xab\xab\xab\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00", 32), 0, (unsigned char *) "PADDING 4a"); asrt(l, 32, (unsigned char *) "PADDING 4b"); aes_remove_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab\xab\xab\xab", 19), 0, (unsigned char *) "PADDING 4c"); asrt(l, 19, (unsigned char *) "PADDING 4d"); fprintf(stderr, "\n"); l = 32; memset(a, 0xab, 48); aes_add_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab\xab\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00\x00\x00", 48), 0, (unsigned char *) "PADDING 5a"); asrt(l, 48, (unsigned char *) "PADDING 5b"); aes_remove_padding(a, &l); asrt(memcmp(a, "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab\xab" "\xab\xab", 32), 0, (unsigned char *) "PADDING 5c"); asrt(l, 32, (unsigned char *) "PADDING 5d"); fprintf(stderr, "\n"); l = 0; memset(a, 0xab, 48); aes_add_padding(a, &l); asrt(memcmp(a, "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" "\x00", 16), 0, (unsigned char *) "PADDING 6a"); asrt(l, 16, (unsigned char *) "PADDING 6b"); aes_remove_padding(a, &l); asrt(memcmp(a, "", 0), 0, (unsigned char *) "PADDING 6c"); asrt(l, 0, (unsigned char *) "PADDING 6d"); fprintf(stderr, "\n"); return EXIT_SUCCESS; } yubihsm-shell-2.6.0/aes_cmac/aes_cmac.c0000644000175100001770000000603314666527773017334 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ // AES-CMAC implementation as defined in SP-800-38B // AES key length can be one of 128, 192, 256 // Output length is one full block (16 bytes) #include #include #include #include "aes_cmac.h" #include "../common/insecure_memzero.h" static const uint8_t zero[AES_BLOCK_SIZE] = {0}; static void do_pad(uint8_t *data, uint8_t len) { for (uint8_t i = len; i < AES_BLOCK_SIZE; i++) if (i == len) data[i] = 0x80; else data[i] = 0x00; } static void do_xor(const uint8_t *a, uint8_t *b) { for (uint8_t i = 0; i < AES_BLOCK_SIZE; i++) { b[i] ^= a[i]; } } static void do_shift_one_bit_left(const uint8_t *a, uint8_t *b, uint8_t *carry) { for (int8_t i = AES_BLOCK_SIZE - 1; i >= 0; i--) { b[i] = (a[i] << 1) | *carry; *carry = a[i] >> 7; } } static void cmac_generate_subkey(const uint8_t *key, uint8_t *subkey) { uint8_t carry = 0; do_shift_one_bit_left(key, subkey, &carry); subkey[AES_BLOCK_SIZE - 1] ^= 0x87 >> (8 - (carry * 8)); } int aes_cmac_encrypt(aes_cmac_context_t *ctx, const uint8_t *message, const uint16_t message_len, uint8_t *mac) { uint8_t M[AES_BLOCK_SIZE] = {0}; const uint8_t *ptr = message; memcpy(mac, zero, AES_BLOCK_SIZE); uint8_t n_blocks; if (message_len == 0) n_blocks = 0; else n_blocks = (message_len + (AES_BLOCK_SIZE - 1)) / AES_BLOCK_SIZE - 1; for (uint8_t i = 0; i < n_blocks; i++) { int rc = aes_cbc_encrypt(ptr, mac, AES_BLOCK_SIZE, mac, ctx->aes_ctx); if (rc) { return rc; } ptr += AES_BLOCK_SIZE; } uint8_t remaining_bytes = (message_len % AES_BLOCK_SIZE); if (remaining_bytes == 0) { if (message != NULL && message_len != 0) { memcpy(M, ptr, AES_BLOCK_SIZE); do_xor(ctx->k1, M); } else { do_pad(M, 0); do_xor(ctx->k2, M); } } else { memcpy(M, ptr, remaining_bytes); do_pad(M, remaining_bytes); do_xor(ctx->k2, M); } return aes_cbc_encrypt(M, mac, AES_BLOCK_SIZE, mac, ctx->aes_ctx); } int aes_cmac_init(aes_context *aes_ctx, aes_cmac_context_t *ctx) { uint8_t L[AES_BLOCK_SIZE] = {0}; ctx->aes_ctx = aes_ctx; int rc = aes_encrypt(zero, L, ctx->aes_ctx); if (rc) { return rc; } cmac_generate_subkey(L, ctx->k1); cmac_generate_subkey(ctx->k1, ctx->k2); return 0; } void aes_cmac_destroy(aes_cmac_context_t *ctx) { if (ctx) { insecure_memzero(ctx, sizeof(aes_cmac_context_t)); } } yubihsm-shell-2.6.0/aes_cmac/aes.c0000644000175100001770000002730714666527773016360 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "aes.h" #include "../common/insecure_memzero.h" #include #include #include #ifdef _WIN32_BCRYPT #include #endif #ifdef _WIN32_BCRYPT static NTSTATUS init_ctx(aes_context *ctx) { NTSTATUS status = STATUS_SUCCESS; BCRYPT_ALG_HANDLE hAlgCBC = 0; BCRYPT_ALG_HANDLE hAlgECB = 0; DWORD cbKeyObj = 0; DWORD cbData = 0; if (!ctx) { return STATUS_INVALID_PARAMETER; } if (ctx->hAlgCBC) { return STATUS_SUCCESS; } /* clear the context, to "reset" */ insecure_memzero(ctx, sizeof(aes_context)); if (!BCRYPT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAlgCBC, BCRYPT_AES_ALGORITHM, NULL, 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptSetProperty(hAlgCBC, BCRYPT_CHAINING_MODE, (PBYTE) BCRYPT_CHAIN_MODE_CBC, sizeof(BCRYPT_CHAIN_MODE_CBC), 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAlgECB, BCRYPT_AES_ALGORITHM, NULL, 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptSetProperty(hAlgECB, BCRYPT_CHAINING_MODE, (PBYTE) BCRYPT_CHAIN_MODE_ECB, sizeof(BCRYPT_CHAIN_MODE_ECB), 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptGetProperty(hAlgCBC, BCRYPT_OBJECT_LENGTH, (PBYTE) &cbKeyObj, sizeof(DWORD), &cbData, 0))) { goto cleanup; } ctx->hAlgCBC = hAlgCBC; hAlgCBC = 0; ctx->hAlgECB = hAlgECB; hAlgECB = 0; ctx->cbKeyObj = cbKeyObj; cleanup: if (hAlgCBC) { BCryptCloseAlgorithmProvider(hAlgCBC, 0); } if (hAlgECB) { BCryptCloseAlgorithmProvider(hAlgECB, 0); } return status; } static NTSTATUS import_key(BCRYPT_ALG_HANDLE hAlg, BCRYPT_KEY_HANDLE *phKey, PBYTE *ppbKeyObj, DWORD cbKeyObj, const uint8_t *key, size_t key_len) { NTSTATUS status = STATUS_SUCCESS; PBYTE pbKeyObj = NULL; BCRYPT_KEY_HANDLE hKey = 0; PBYTE pbKeyBlob = NULL; DWORD cbKeyBlob = 0; if (!phKey || !ppbKeyObj) { return STATUS_INVALID_PARAMETER; } /* close existing key first */ if (*phKey) { BCryptDestroyKey(*phKey); *phKey = 0; } /* free existing key object */ if (*ppbKeyObj) { free(*ppbKeyObj); *ppbKeyObj = NULL; } /* allocate new key object */ if (!(pbKeyObj = (PBYTE) malloc(cbKeyObj))) { status = STATUS_NO_MEMORY; goto cleanup; } cbKeyBlob = (DWORD) (sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + key_len); if (!(pbKeyBlob = (PBYTE) malloc(cbKeyBlob))) { status = STATUS_NO_MEMORY; goto cleanup; } /* set up BCrypt Key Blob for import */ ((BCRYPT_KEY_DATA_BLOB_HEADER *) pbKeyBlob)->dwMagic = BCRYPT_KEY_DATA_BLOB_MAGIC; ((BCRYPT_KEY_DATA_BLOB_HEADER *) pbKeyBlob)->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1; ((BCRYPT_KEY_DATA_BLOB_HEADER *) pbKeyBlob)->cbKeyData = (DWORD) key_len; memcpy(pbKeyBlob + sizeof(BCRYPT_KEY_DATA_BLOB_HEADER), key, key_len); if (!BCRYPT_SUCCESS(status = BCryptImportKey(hAlg, NULL, BCRYPT_KEY_DATA_BLOB, &hKey, pbKeyObj, cbKeyObj, pbKeyBlob, cbKeyBlob, 0))) { goto cleanup; } /* set output params */ *phKey = hKey; hKey = 0; *ppbKeyObj = pbKeyObj; pbKeyObj = 0; cleanup: if (hKey) { BCryptDestroyKey(hKey); } if (pbKeyObj) { free(pbKeyObj); } if (pbKeyBlob) { free(pbKeyBlob); } return !BCRYPT_SUCCESS(status); } #else static const EVP_CIPHER *aes_ecb(uint16_t key_len) { switch (key_len) { case 16: return EVP_aes_128_ecb(); case 24: return EVP_aes_192_ecb(); case 32: return EVP_aes_256_ecb(); default: return NULL; } } static const EVP_CIPHER *aes_cbc(uint16_t key_len) { switch (key_len) { case 16: return EVP_aes_128_cbc(); case 24: return EVP_aes_192_cbc(); case 32: return EVP_aes_256_cbc(); default: return NULL; } } static int aes_encrypt_ex(const EVP_CIPHER *cipher, const uint8_t *in, uint8_t *out, uint16_t len, const uint8_t *iv, aes_context *ctx) { if (EVP_EncryptInit_ex(ctx->ctx, cipher, NULL, ctx->key, iv) != 1) { return -1; } if (EVP_CIPHER_CTX_set_padding(ctx->ctx, 0) != 1) { return -2; } int update_len = len; if (EVP_EncryptUpdate(ctx->ctx, out, &update_len, in, len) != 1) { return -3; } int final_len = len - update_len; if (EVP_EncryptFinal_ex(ctx->ctx, out + update_len, &final_len) != 1) { return -4; } if (update_len + final_len != len) { return -5; } return 0; } static int aes_decrypt_ex(const EVP_CIPHER *cipher, const uint8_t *in, uint8_t *out, uint16_t len, const uint8_t *iv, aes_context *ctx) { if (EVP_DecryptInit_ex(ctx->ctx, cipher, NULL, ctx->key, iv) != 1) { return -1; } if (EVP_CIPHER_CTX_set_padding(ctx->ctx, 0) != 1) { return -2; } int update_len = len; if (EVP_DecryptUpdate(ctx->ctx, out, &update_len, in, len) != 1) { return -3; } int final_len = len - update_len; if (EVP_DecryptFinal_ex(ctx->ctx, out + update_len, &final_len) != 1) { return -4; } if (update_len + final_len != len) { return -5; } return 0; } #endif int aes_set_key(const uint8_t *key, uint16_t key_len, aes_context *ctx) { #ifdef _WIN32_BCRYPT NTSTATUS status = STATUS_SUCCESS; if (!BCRYPT_SUCCESS(status = init_ctx(ctx))) { return -1; } if (!BCRYPT_SUCCESS(status = import_key(ctx->hAlgCBC, &(ctx->hKeyCBC), &(ctx->pbKeyCBCObj), ctx->cbKeyObj, key, key_len))) { return -2; } if (!BCRYPT_SUCCESS(status = import_key(ctx->hAlgECB, &(ctx->hKeyECB), &(ctx->pbKeyECBObj), ctx->cbKeyObj, key, key_len))) { return -3; } #else if (key == NULL || aes_ecb(key_len) == NULL) { return -1; } if (!ctx->ctx) { ctx->ctx = EVP_CIPHER_CTX_new(); if (!ctx->ctx) { return -2; } } ctx->key_len = key_len; memcpy(ctx->key, key, key_len); #endif return 0; } int aes_load_key(const char *key, aes_context *ctx) { #ifdef _WIN32_BCRYPT (void) key; (void) ctx; return -1; #else const uint8_t default_enc[] = {0x09, 0x0b, 0x47, 0xdb, 0xed, 0x59, 0x56, 0x54, 0x90, 0x1d, 0xee, 0x1c, 0xc6, 0x55, 0xe4, 0x20}; const uint8_t default_mac[] = {0x59, 0x2f, 0xd4, 0x83, 0xf7, 0x59, 0xe2, 0x99, 0x09, 0xa0, 0x4c, 0x45, 0x05, 0xd2, 0xce, 0x0a}; ctx->key_len = sizeof(default_enc); if (key == NULL || aes_ecb(ctx->key_len) == NULL) { return -1; } if (!ctx->ctx) { ctx->ctx = EVP_CIPHER_CTX_new(); if (!ctx->ctx) { return -2; } } if (!strcmp(key, "default_enc")) memcpy(ctx->key, default_enc, ctx->key_len); else if (!strcmp(key, "default_mac")) memcpy(ctx->key, default_mac, ctx->key_len); else memset(ctx->key, 0, ctx->key_len); return 0; #endif } int aes_encrypt(const uint8_t *in, uint8_t *out, aes_context *ctx) { #ifdef _WIN32_BCRYPT NTSTATUS status = STATUS_SUCCESS; ULONG cbResult = 0; if (!BCRYPT_SUCCESS(status = BCryptEncrypt(ctx->hKeyECB, (PUCHAR) in, AES_BLOCK_SIZE, NULL, NULL, 0, out, AES_BLOCK_SIZE, &cbResult, 0))) { return -1; } if (cbResult != AES_BLOCK_SIZE) { return -2; } return 0; #else return aes_encrypt_ex(aes_ecb(ctx->key_len), in, out, AES_BLOCK_SIZE, NULL, ctx); #endif } int aes_decrypt(const uint8_t *in, uint8_t *out, aes_context *ctx) { #ifdef _WIN32_BCRYPT NTSTATUS status = STATUS_SUCCESS; ULONG cbResult = 0; if (!BCRYPT_SUCCESS(status = BCryptDecrypt(ctx->hKeyECB, (PUCHAR) in, AES_BLOCK_SIZE, NULL, NULL, 0, out, AES_BLOCK_SIZE, &cbResult, 0))) { return -1; } if (cbResult != AES_BLOCK_SIZE) { return -2; } return 0; #else return aes_decrypt_ex(aes_ecb(ctx->key_len), in, out, AES_BLOCK_SIZE, NULL, ctx); #endif } int aes_cbc_encrypt(const uint8_t *in, uint8_t *out, uint16_t len, const uint8_t *iv, aes_context *ctx) { #ifdef _WIN32_BCRYPT NTSTATUS status = STATUS_SUCCESS; ULONG cbResult = 0; UCHAR _iv[AES_BLOCK_SIZE]; memcpy(_iv, iv, AES_BLOCK_SIZE); if (!BCRYPT_SUCCESS(status = BCryptEncrypt(ctx->hKeyCBC, (PUCHAR) in, len, NULL, _iv, AES_BLOCK_SIZE, out, len, &cbResult, 0))) { return -1; } if (cbResult != len) { return -2; } return 0; #else return aes_encrypt_ex(aes_cbc(ctx->key_len), in, out, len, iv, ctx); #endif } int aes_cbc_decrypt(const uint8_t *in, uint8_t *out, uint16_t len, const uint8_t *iv, aes_context *ctx) { #ifdef _WIN32_BCRYPT NTSTATUS status = STATUS_SUCCESS; ULONG cbResult = 0; UCHAR _iv[AES_BLOCK_SIZE]; memcpy(_iv, iv, AES_BLOCK_SIZE); if (!BCRYPT_SUCCESS(status = BCryptDecrypt(ctx->hKeyCBC, (PUCHAR) in, len, NULL, _iv, AES_BLOCK_SIZE, out, len, &cbResult, 0))) { return -1; } if (cbResult != len) { return -2; } return 0; #else return aes_decrypt_ex(aes_cbc(ctx->key_len), in, out, len, iv, ctx); #endif } int aes_add_padding(uint8_t *in, uint16_t max_len, uint16_t *len) { uint16_t new_len = *len; if (in) { if (new_len >= max_len) { return -1; } in[new_len] = 0x80; } new_len++; while (new_len % AES_BLOCK_SIZE != 0) { if (in) { if (new_len >= max_len) { return -2; } in[new_len] = 0x00; } new_len++; } *len = new_len; return 0; } void aes_remove_padding(uint8_t *in, uint16_t *len) { while ((*len) > 1 && in[(*len) - 1] == 0) { (*len)--; } if (*len > 0) (*len)--; } void aes_destroy(aes_context *ctx) { if (!ctx) { return; } #ifdef _WIN32_BCRYPT if (ctx->hKeyCBC) { BCryptDestroyKey(ctx->hKeyCBC); } if (ctx->pbKeyCBCObj) { free(ctx->pbKeyCBCObj); } if (ctx->hKeyECB) { BCryptDestroyKey(ctx->hKeyECB); } if (ctx->pbKeyECBObj) { free(ctx->pbKeyECBObj); } if (ctx->hAlgCBC) { BCryptCloseAlgorithmProvider(ctx->hAlgCBC, 0); } if (ctx->hAlgECB) { BCryptCloseAlgorithmProvider(ctx->hAlgECB, 0); } #else EVP_CIPHER_CTX_free(ctx->ctx); #endif insecure_memzero(ctx, sizeof(aes_context)); } yubihsm-shell-2.6.0/ykhsmauth/0000755000175100001770000000000014666527773015715 5ustar runnerdockeryubihsm-shell-2.6.0/ykhsmauth/CMakeLists.txt0000644000175100001770000000415314666527773020460 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # set ( SOURCE error.c ykhsmauth.c ) if(WIN32) set(SOURCE ${SOURCE} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) endif(WIN32) include_directories ( ${LIBPCSC_INCLUDEDIR} ) add_library (ykhsmauth SHARED ${SOURCE}) #add_definitions (-DVERSION="${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") target_link_libraries (ykhsmauth ${LIBPCSC_LDFLAGS}) set_target_properties (ykhsmauth PROPERTIES VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}" SOVERSION ${yubihsm_shell_VERSION_MAJOR}) # Set install RPATH set_target_properties(ykhsmauth PROPERTIES INSTALL_RPATH "${YUBIHSM_INSTALL_LIB_DIR}") add_library (ykhsmauth_static STATIC ${SOURCE}) set_target_properties (ykhsmauth_static PROPERTIES POSITION_INDEPENDENT_CODE on OUTPUT_NAME ykhsmauth) set_target_properties (ykhsmauth_static PROPERTIES COMPILE_FLAGS "-DSTATIC") target_link_libraries (ykhsmauth_static ${LIBPCSC_LDFLAGS}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ykhsmauth.pc.in ${CMAKE_CURRENT_BINARY_DIR}/ykhsmauth.pc @ONLY) if(WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) endif(WIN32) install( TARGETS ykhsmauth ARCHIVE DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" RUNTIME DESTINATION "${YUBIHSM_INSTALL_BIN_DIR}") install(FILES ykhsmauth.h DESTINATION ${YUBIHSM_INSTALL_INC_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ykhsmauth.pc DESTINATION ${YUBIHSM_INSTALL_PKGCONFIG_DIR}) yubihsm-shell-2.6.0/ykhsmauth/internal.h0000644000175100001770000000221614666527773017703 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YKHSMAUTH_INTERNAL_H #define YKHSMAUTH_INTERNAL_H #include #if defined(_WIN32) #include #else #include #include #endif #define READER_LEN 32 #define MAX_READERS 16 struct ykhsmauth_state { SCARDCONTEXT context; SCARDHANDLE card; int verbose; }; union u_APDU { struct { unsigned char cla; unsigned char ins; unsigned char p1; unsigned char p2; unsigned char lc; unsigned char data[0xff]; } st; unsigned char raw[0xff + 5]; }; typedef union u_APDU APDU; #endif yubihsm-shell-2.6.0/ykhsmauth/ykhsmauth.pc.in0000644000175100001770000000041314666527773020661 0ustar runnerdockerlibdir=-L@YUBIHSM_INSTALL_LIB_DIR@ includedir=@YUBIHSM_INSTALL_INC_DIR@ Name: ykhsmauth Description: Yubico YubiHSM application for YubiKey C Library URL: https://www.yubico.com/ Version: @VERSION@ Requires.private: libcrypto libpcsclite Libs: ${libdir} -lykhsmauth yubihsm-shell-2.6.0/ykhsmauth/ykhsmauth.h0000644000175100001770000001614014666527773020105 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YKHSMAUTH_H #define YKHSMAUTH_H #include #include //#include #ifdef __cplusplus extern "C" { #endif // INS codes #define YKHSMAUTH_INS_PUT 0x01 #define YKHSMAUTH_INS_DELETE 0x02 #define YKHSMAUTH_INS_CALCULATE 0x03 #define YKHSMAUTH_INS_GET_CHALLENGE 0x04 #define YKHSMAUTH_INS_LIST 0x05 #define YKHSMAUTH_INS_RESET 0x06 #define YKHSMAUTH_INS_GET_VERSION 0x07 #define YKHSMAUTH_INS_PUT_MGMKEY 0x08 #define YKHSMAUTH_INS_GET_MGMKEY_RETRIES 0x09 #define YKHSMAUTH_INS_GET_PUBKEY 0x0a // P1 bytes #define YKHSMAUTH_P1_RESET 0xde // P2 bytes #define YKHSMAUTH_P2_RESET 0xad // Tag codes #define YKHSMAUTH_TAG_LABEL 0x71 #define YKHSMAUTH_TAG_LABEL_LIST 0x72 #define YKHSMAUTH_TAG_PW 0x73 #define YKHSMAUTH_TAG_ALGO 0x74 #define YKHSMAUTH_TAG_KEY_ENC 0x75 #define YKHSMAUTH_TAG_KEY_MAC 0x76 #define YKHSMAUTH_TAG_CONTEXT 0x77 #define YKHSMAUTH_TAG_RESPONSE 0x78 #define YKHSMAUTH_TAG_VERSION 0x79 #define YKHSMAUTH_TAG_TOUCH 0x7a #define YKHSMAUTH_TAG_MGMKEY 0x7b #define YKHSMAUTH_TAG_PUBKEY 0x7c #define YKHSMAUTH_TAG_PRIVKEY 0x7d // Algos #define YKHSMAUTH_YUBICO_AES128_ALGO 38 #define YKHSMAUTH_YUBICO_ECP256_ALGO 39 #define SW_SUCCESS 0x9000 #define SW_BYTES_REMAINING_00 0x6100 #define SW_WRONG_LENGTH 0x6700 #define SW_SECURITY_STATUS_NOT_SATISFIED 0x6982 #define SW_FILE_INVALID 0x6983 #define SW_DATA_INVALID 0x6984 #define SW_CONDITIONS_NOT_SATISFIED 0x6985 #define SW_COMMAND_NOT_ALLOWED 0x6986 #define SW_APPLET_SELECT_FAILED 0x6999 #define SW_WRONG_DATA 0x6A80 #define SW_FUNC_NOT_SUPPORTED 0x6A81 #define SW_FILE_NOT_FOUND 0x6A82 #define SW_RECORD_NOT_FOUND 0x6A83 #define SW_INCORRECT_P1P2 0x6A86 #define SW_WRONG_P1P2 0x6B00 #define SW_CORRECT_LENGTH_00 0x6C00 #define SW_INS_NOT_SUPPORTED 0x6D00 #define SW_CLA_NOT_SUPPORTED 0x6E00 #define SW_UNKNOWN 0x6F00 #define SW_FILE_FULL 0x6A84 #define SW_LOGICAL_CHANNEL_NOT_SUPPORTED 0x6881 #define SW_SECURE_MESSAGING_NOT_SUPPORTED 0x6882 #define SW_WARNING_STATE_UNCHANGED 0x6200 #define SW_LAST_COMMAND_EXPECTED 0x6883 #define SW_COMMAND_CHAINING_NOT_SUPPORTED 0x6884 #define SW_AUTHENTICATION_BLOCKED 0x6983 #define SW_AUTHENTICATION_FAILED 0x63C0 #define SW_MEMORY_ERROR 0x6581 // Lengths #define YKHSMAUTH_MIN_LABEL_LEN 1 #define YKHSMAUTH_MAX_LABEL_LEN 64 #define YKHSMAUTH_SESSION_KEY_LEN 16 #define YKHSMAUTH_CARD_CRYPTO_LEN 8 #define YKHSMAUTH_HOST_CRYPTO_LEN 8 #define YKHSMAUTH_YUBICO_AES128_KEY_LEN 32 #define YKHSMAUTH_PW_LEN 16 #define YKHSMAUTH_CONTEXT_LEN 16 #define YKHSMAUTH_YUBICO_ECP256_PUBKEY_LEN 65 #define YKHSMAUTH_YUBICO_ECP256_PRIVKEY_LEN 32 // PBKDF2 derivation parameters #define YKHSMAUTH_DEFAULT_SALT "Yubico" #define YKHSMAUTH_DEFAULT_ITERS 10000 typedef struct ykhsmauth_state ykhsmauth_state; typedef enum { YKHSMAUTHR_SUCCESS = 0, YKHSMAUTHR_MEMORY_ERROR = -1, YKHSMAUTHR_PCSC_ERROR = -2, YKHSMAUTHR_GENERIC_ERROR = -3, YKHSMAUTHR_WRONG_PW = -4, YKHSMAUTHR_INVALID_PARAMS = -5, YKHSMAUTHR_ENTRY_NOT_FOUND = -6, YKHSMAUTHR_STORAGE_FULL = -7, YKHSMAUTHR_TOUCH_ERROR = -8, YKHSMAUTHR_ENTRY_INVALID = -9, YKHSMAUTHR_DATA_INVALID = -10, YKHSMAUTHR_NOT_SUPPORTED = -11, } ykhsmauth_rc; typedef struct { uint8_t algo; uint8_t touch; char label[YKHSMAUTH_MAX_LABEL_LEN + 1]; uint8_t ctr; } ykhsmauth_list_entry; const char *ykhsmauth_strerror(ykhsmauth_rc err); const char *ykhsmauth_strerror_name(ykhsmauth_rc err); ykhsmauth_rc ykhsmauth_init(ykhsmauth_state **state, int verbose); ykhsmauth_rc ykhsmauth_done(ykhsmauth_state *state); ykhsmauth_rc ykhsmauth_connect(ykhsmauth_state *state, const char *wanted); ykhsmauth_rc ykhsmauth_list_readers(ykhsmauth_state *state, char *readers, size_t *len); ykhsmauth_rc ykhsmauth_disconnect(ykhsmauth_state *state); ykhsmauth_rc ykhsmauth_get_version_ex(ykhsmauth_state *state, uint8_t *major, uint8_t *minor, uint8_t *patch); ykhsmauth_rc ykhsmauth_get_version(ykhsmauth_state *state, char *version, size_t len); ykhsmauth_rc ykhsmauth_put(ykhsmauth_state *state, const uint8_t *mgmkey, size_t mgmkey_len, const char *label, uint8_t algo, const uint8_t *key, size_t key_len, const uint8_t *pw, size_t pw_len, const uint8_t touch_policy, uint8_t *retries); ykhsmauth_rc ykhsmauth_delete(ykhsmauth_state *state, uint8_t *mgmkey, size_t mgmkey_len, char *label, uint8_t *retries); ykhsmauth_rc ykhsmauth_calculate(ykhsmauth_state *state, const char *label, uint8_t *context, size_t context_len, const uint8_t *pw, size_t pw_len, uint8_t *key_s_enc, size_t key_s_enc_len, uint8_t *key_s_mac, size_t key_s_mac_len, uint8_t *key_s_rmac, size_t key_s_rmac_len, uint8_t *retries); ykhsmauth_rc ykhsmauth_calculate_ex( ykhsmauth_state *state, const char *label, uint8_t *context, size_t context_len, uint8_t *card_pubkey, size_t card_pubkey_len, uint8_t *card_crypto, size_t card_crypto_len, const uint8_t *pw, size_t pw_len, uint8_t *key_s_enc, size_t key_s_enc_len, uint8_t *key_s_mac, size_t key_s_mac_len, uint8_t *key_s_rmac, size_t key_s_rmac_len, uint8_t *retries); ykhsmauth_rc ykhsmauth_reset(ykhsmauth_state *state); ykhsmauth_rc ykhsmauth_list_keys(ykhsmauth_state *state, ykhsmauth_list_entry *list, size_t *list_items); ykhsmauth_rc ykhsmauth_get_challenge(ykhsmauth_state *state, const char *label, uint8_t *challenge, size_t *challenge_len); ykhsmauth_rc ykhsmauth_get_challenge_ex(ykhsmauth_state *state, const char *label, const uint8_t *cpw, size_t cpw_len, uint8_t *challenge, size_t *challenge_len); ykhsmauth_rc ykhsmauth_get_pubkey(ykhsmauth_state *state, const char *label, uint8_t *pubkey, size_t *pubkey_len); ykhsmauth_rc ykhsmauth_get_mgmkey_retries(ykhsmauth_state *state, uint8_t *retries); ykhsmauth_rc ykhsmauth_put_mgmkey(ykhsmauth_state *state, uint8_t *mgmkey, size_t mgmkey_len, uint8_t *new_mgmkey, size_t new_mgmkey_len, uint8_t *retries); #ifdef __cplusplus } #endif #ifdef _MSC_VER #pragma strict_gs_check(on) #endif #endif yubihsm-shell-2.6.0/ykhsmauth/ykhsmauth.c0000644000175100001770000005316114666527773020104 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "internal.h" #include "ykhsmauth.h" #ifdef _WIN32 #define strncasecmp _strnicmp #endif static uint16_t encode_len(uint8_t *buf, uint16_t len) { if (len > 0xff) { *buf++ = 0x82; *buf++ = len >> 8; *buf++ = len; return 3; } if (len > 0x7f) { *buf++ = 0x81; *buf++ = len; return 2; } *buf++ = len; return 1; } static void add_tag(APDU *apdu, uint8_t tag, const void *data, uint16_t len, uint16_t pad) { uint8_t *ptr = apdu->st.data + apdu->st.lc; *ptr++ = tag; ptr += encode_len(ptr, len + pad); memcpy(ptr, data, len); ptr += len; memset(ptr, 0, pad); ptr += pad; apdu->st.lc = ptr - apdu->st.data; } static ykhsmauth_rc translate_error(uint16_t sw, uint8_t *retries) { if ((sw & 0xfff0) == SW_AUTHENTICATION_FAILED) { if (retries != NULL) { *retries = sw & ~0xfff0; } return YKHSMAUTHR_WRONG_PW; } else if (sw == SW_FILE_FULL) { return YKHSMAUTHR_STORAGE_FULL; } else if (sw == SW_FILE_NOT_FOUND) { return YKHSMAUTHR_ENTRY_NOT_FOUND; } else if (sw == SW_WRONG_DATA) { return YKHSMAUTHR_INVALID_PARAMS; } else if (sw == SW_MEMORY_ERROR) { return YKHSMAUTHR_MEMORY_ERROR; } else if (sw == SW_SECURITY_STATUS_NOT_SATISFIED) { return YKHSMAUTHR_TOUCH_ERROR; } else if (sw == SW_FILE_INVALID) { return YKHSMAUTHR_ENTRY_INVALID; } else if (sw == SW_DATA_INVALID) { return YKHSMAUTHR_DATA_INVALID; } else if (sw == SW_INS_NOT_SUPPORTED) { return YKHSMAUTHR_NOT_SUPPORTED; } else { return YKHSMAUTHR_GENERIC_ERROR; } } ykhsmauth_rc ykhsmauth_init(ykhsmauth_state **state, int verbose) { if (state == NULL) { if (verbose) { fprintf(stderr, "Unable to initialize: %s\n", ykhsmauth_strerror(YKHSMAUTHR_INVALID_PARAMS)); } return YKHSMAUTHR_INVALID_PARAMS; } ykhsmauth_state *s = calloc(1, sizeof(ykhsmauth_state)); if (s == NULL) { if (verbose) { fprintf(stderr, "Unable to initialize: %s\n", ykhsmauth_strerror(YKHSMAUTHR_MEMORY_ERROR)); } return YKHSMAUTHR_MEMORY_ERROR; } s->verbose = verbose; *state = s; return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_done(ykhsmauth_state *state) { ykhsmauth_disconnect(state); if (state == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } SCardReleaseContext(state->context); state->context = 0; free(state); return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_disconnect(ykhsmauth_state *state) { if (state == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } if (state->card) { SCardDisconnect(state->card, SCARD_RESET_CARD); state->card = 0; } return YKHSMAUTHR_SUCCESS; } static void dump_hex(const unsigned char *buf, DWORD len) { for (DWORD i = 0; i < len; i++) { fprintf(stderr, "%02x ", buf[i]); } } static ykhsmauth_rc send_data(ykhsmauth_state *state, const APDU *apdu, unsigned char *data, LPDWORD recv_len, uint16_t *sw) { DWORD send_len = apdu->st.lc + 5; *sw = 0; if (state->verbose > 1) { fprintf(stderr, "> "); dump_hex(apdu->raw, send_len); fprintf(stderr, "\n"); } int32_t rc = SCardTransmit(state->card, SCARD_PCI_T1, apdu->raw, send_len, NULL, data, recv_len); if (rc != SCARD_S_SUCCESS) { if (state->verbose) { fprintf(stderr, "SCardTransmit failed, rc=%08x\n", rc); } return YKHSMAUTHR_PCSC_ERROR; } if (state->verbose > 1) { fprintf(stderr, "< "); dump_hex(data, *recv_len); fprintf(stderr, "\n"); } if (*recv_len >= 2) { *sw = (data[*recv_len - 2] << 8) | data[*recv_len - 1]; *recv_len -= 2; } return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_connect(ykhsmauth_state *state, const char *wanted) { if (state == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } char readers[2048] = {0}; size_t readers_len = sizeof(readers); ykhsmauth_rc ret = ykhsmauth_list_readers(state, readers, &readers_len); if (ret != YKHSMAUTHR_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to list_readers: %s\n", ykhsmauth_strerror(ret)); } return ret; } for (char *reader_ptr = readers; *reader_ptr != '\0'; reader_ptr += strlen(reader_ptr) + 1) { if (wanted) { bool found = false; char *ptr = reader_ptr; while (strlen(ptr) >= strlen(wanted)) { if (strncasecmp(ptr, wanted, strlen(wanted)) == 0) { found = true; break; } ptr++; } if (found == false) { if (state->verbose) { fprintf(stderr, "Skipping reader '%s' since it doesn't match '%s'\n", reader_ptr, wanted); } continue; } } if (state->verbose) { fprintf(stderr, "Trying to connect to reader '%s'\n", reader_ptr); } DWORD active_protocol = 0; int32_t rc = SCardConnect(state->context, reader_ptr, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T1, &state->card, &active_protocol); if (rc != SCARD_S_SUCCESS) { if (state->verbose) { fprintf(stderr, "SCardConnect failed, rc=%08x\n", rc); } continue; } APDU apdu = { {0, 0xa4, 0x04, 0, 8, {0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x07, 0x01}}}; unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; if ((ret = send_data(state, &apdu, data, &recv_len, &sw)) != YKHSMAUTHR_SUCCESS) { if (state->verbose) { fprintf(stderr, "Failed communicating with card: '%s'\n", ykhsmauth_strerror(ret)); } } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Failed selecting application: %04x\n", sw); } } else { return YKHSMAUTHR_SUCCESS; } if (state->verbose) { fprintf(stderr, "Disconnecting reader '%s'\n", reader_ptr); } SCardDisconnect(state->card, SCARD_LEAVE_CARD); state->card = 0; } if (state->verbose) { fprintf(stderr, "No usable reader found\n"); } return YKHSMAUTHR_GENERIC_ERROR; } ykhsmauth_rc ykhsmauth_list_readers(ykhsmauth_state *state, char *readers, size_t *len) { if (state == NULL || readers == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } if (SCardIsValidContext(state->context) != SCARD_S_SUCCESS) { state->card = 0; int32_t rc = SCardEstablishContext(SCARD_SCOPE_SYSTEM, NULL, NULL, &state->context); if (rc != SCARD_S_SUCCESS) { if (state->verbose) { fprintf(stderr, "SCardEstablishContext failed, rc=%08x\n", rc); } return YKHSMAUTHR_PCSC_ERROR; } } DWORD readers_len = *len; int32_t rc = SCardListReaders(state->context, NULL, readers, &readers_len); if (rc != SCARD_S_SUCCESS) { if (state->verbose) { fprintf(stderr, "SCardListReaders failed rc=%08x\n", rc); } return YKHSMAUTHR_PCSC_ERROR; } *len = readers_len; return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_get_version_ex(ykhsmauth_state *state, uint8_t *major, uint8_t *minor, uint8_t *patch) { if (state == NULL || major == NULL || minor == NULL || patch == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_GET_VERSION, 0, 0, 0, {0}}}; unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc res; if ((res = send_data(state, &apdu, data, &recv_len, &sw)) != YKHSMAUTHR_SUCCESS) { return res; } else if (sw == SW_SUCCESS && recv_len == 3) { *major = data[0]; *minor = data[1]; *patch = data[2]; return YKHSMAUTHR_SUCCESS; } else { return translate_error(sw, NULL); } } ykhsmauth_rc ykhsmauth_get_version(ykhsmauth_state *state, char *version, size_t len) { if (version == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } uint8_t v[3] = {0}; ykhsmauth_rc res = ykhsmauth_get_version_ex(state, &v[0], &v[1], &v[2]); if(res == YKHSMAUTHR_SUCCESS) { int result = snprintf(version, len, "%d.%d.%d", v[0], v[1], v[2]); if (result < 0) { if (state->verbose) { fprintf(stderr, "Version buffer too small\n"); } return YKHSMAUTHR_GENERIC_ERROR; } } return res; } ykhsmauth_rc ykhsmauth_put(ykhsmauth_state *state, const uint8_t *mgmkey, size_t mgmkey_len, const char *label, uint8_t algo, const uint8_t *key, size_t key_len, const uint8_t *cpw, size_t cpw_len, const uint8_t touch_policy, uint8_t *retries) { if (state == NULL || mgmkey == NULL || mgmkey_len != YKHSMAUTH_PW_LEN || label == NULL || strlen(label) < YKHSMAUTH_MIN_LABEL_LEN || strlen(label) > YKHSMAUTH_MAX_LABEL_LEN || key == NULL || key_len > YKHSMAUTH_YUBICO_ECP256_PRIVKEY_LEN || cpw == NULL || cpw_len > YKHSMAUTH_PW_LEN) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_PUT, 0, 0, 0, {0}}}; add_tag(&apdu, YKHSMAUTH_TAG_MGMKEY, mgmkey, mgmkey_len, 0); add_tag(&apdu, YKHSMAUTH_TAG_LABEL, label, strlen(label), 0); add_tag(&apdu, YKHSMAUTH_TAG_ALGO, &algo, sizeof(algo), 0); if (algo == YKHSMAUTH_YUBICO_AES128_ALGO) { add_tag(&apdu, YKHSMAUTH_TAG_KEY_ENC, key, key_len / 2, 0); add_tag(&apdu, YKHSMAUTH_TAG_KEY_MAC, key + key_len / 2, key_len / 2, 0); } else if (algo == YKHSMAUTH_YUBICO_ECP256_ALGO) { add_tag(&apdu, YKHSMAUTH_TAG_PRIVKEY, key, key_len, 0); } add_tag(&apdu, YKHSMAUTH_TAG_PW, cpw, cpw_len, YKHSMAUTH_PW_LEN - cpw_len); add_tag(&apdu, YKHSMAUTH_TAG_TOUCH, &touch_policy, sizeof(touch_policy), 0); unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to store credential: %04x\n", sw); } return translate_error(sw, retries); } return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_delete(ykhsmauth_state *state, uint8_t *mgmkey, size_t mgmkey_len, char *label, uint8_t *retries) { if (state == NULL || mgmkey == NULL || mgmkey_len != YKHSMAUTH_PW_LEN || label == NULL || strlen(label) < YKHSMAUTH_MIN_LABEL_LEN || strlen(label) > YKHSMAUTH_MAX_LABEL_LEN) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_DELETE, 0, 0, 0, {0}}}; add_tag(&apdu, YKHSMAUTH_TAG_MGMKEY, mgmkey, mgmkey_len, 0); add_tag(&apdu, YKHSMAUTH_TAG_LABEL, label, strlen(label), 0); unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to delete credential: %04x\n", sw); } return translate_error(sw, retries); } return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_calculate(ykhsmauth_state *state, const char *label, uint8_t *context, size_t context_len, const uint8_t *pw, size_t pw_len, uint8_t *key_s_enc, size_t key_s_enc_len, uint8_t *key_s_mac, size_t key_s_mac_len, uint8_t *key_s_rmac, size_t key_s_rmac_len, uint8_t *retries) { return ykhsmauth_calculate_ex(state, label, context, context_len, NULL, 0, NULL, 0, pw, pw_len, key_s_enc, key_s_enc_len, key_s_mac, key_s_mac_len, key_s_rmac, key_s_rmac_len, retries); } ykhsmauth_rc ykhsmauth_calculate_ex( ykhsmauth_state *state, const char *label, uint8_t *context, size_t context_len, uint8_t *card_pubkey, size_t card_pubkey_len, uint8_t *card_crypto, size_t card_crypto_len, const uint8_t *pw, size_t pw_len, uint8_t *key_s_enc, size_t key_s_enc_len, uint8_t *key_s_mac, size_t key_s_mac_len, uint8_t *key_s_rmac, size_t key_s_rmac_len, uint8_t *retries) { if (state == NULL || label == NULL || strlen(label) < YKHSMAUTH_MIN_LABEL_LEN || strlen(label) > YKHSMAUTH_MAX_LABEL_LEN || context == NULL || context_len > 2 * YKHSMAUTH_YUBICO_ECP256_PUBKEY_LEN || card_pubkey_len > YKHSMAUTH_YUBICO_ECP256_PUBKEY_LEN || card_crypto_len > YKHSMAUTH_SESSION_KEY_LEN || pw == NULL || pw_len > YKHSMAUTH_PW_LEN || key_s_enc == NULL || key_s_enc_len != YKHSMAUTH_SESSION_KEY_LEN || key_s_mac == NULL || key_s_mac_len != YKHSMAUTH_SESSION_KEY_LEN || key_s_rmac == NULL || key_s_rmac_len != YKHSMAUTH_SESSION_KEY_LEN) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_CALCULATE, 0, 0, 0, {0}}}; add_tag(&apdu, YKHSMAUTH_TAG_LABEL, label, strlen(label), 0); add_tag(&apdu, YKHSMAUTH_TAG_CONTEXT, context, context_len, 0); if (card_pubkey && card_pubkey_len) { add_tag(&apdu, YKHSMAUTH_TAG_PUBKEY, card_pubkey, card_pubkey_len, 0); } // Only send card_crypto for asym auth if (card_crypto && card_crypto_len > YKHSMAUTH_CARD_CRYPTO_LEN) { add_tag(&apdu, YKHSMAUTH_TAG_RESPONSE, card_crypto, card_crypto_len, 0); } add_tag(&apdu, YKHSMAUTH_TAG_PW, pw, pw_len, YKHSMAUTH_PW_LEN - pw_len); unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to derive keys: %04x\n", sw); } return translate_error(sw, retries); } if (recv_len != 3 * YKHSMAUTH_SESSION_KEY_LEN) { if (state->verbose) { fprintf(stderr, "Wrong length returned: %zu\n", (size_t) recv_len); } return YKHSMAUTHR_GENERIC_ERROR; } uint8_t *ptr = data; memcpy(key_s_enc, ptr, YKHSMAUTH_SESSION_KEY_LEN); ptr += YKHSMAUTH_SESSION_KEY_LEN; memcpy(key_s_mac, ptr, YKHSMAUTH_SESSION_KEY_LEN); ptr += YKHSMAUTH_SESSION_KEY_LEN; memcpy(key_s_rmac, ptr, YKHSMAUTH_SESSION_KEY_LEN); ptr += YKHSMAUTH_SESSION_KEY_LEN; // Ignore host crypto for now return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_reset(ykhsmauth_state *state) { if (state == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = { {0, YKHSMAUTH_INS_RESET, YKHSMAUTH_P1_RESET, YKHSMAUTH_P2_RESET, 0, {0}}}; unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc res = send_data(state, &apdu, data, &recv_len, &sw); if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to reset: %s\n", ykhsmauth_strerror(res)); } return translate_error(sw, NULL); } return res; } ykhsmauth_rc ykhsmauth_list_keys(ykhsmauth_state *state, ykhsmauth_list_entry *list, size_t *list_items) { if (state == NULL || list_items == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_LIST, 0, 0, 0, {0}}}; unsigned char data[1024] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to list keys: %04x\n", sw); } return translate_error(sw, NULL); } size_t element = 0; size_t i = 0; // i + 1 here guarantees we can read tag and len while (i + 1 < recv_len) { if (data[i++] == YKHSMAUTH_TAG_LABEL_LIST) { size_t len = data[i++]; if (list != NULL) { if (element >= *list_items) { return YKHSMAUTHR_MEMORY_ERROR; } else if (i + len > recv_len || len < 3 || len - 3 > sizeof(list[element].label)) { if (state->verbose) { fprintf(stderr, "Length of element doesn't match expectations (%zu)\n", len); } return YKHSMAUTHR_GENERIC_ERROR; } list[element].algo = data[i++]; list[element].touch = data[i++]; memset(list[element].label, 0, sizeof(list[element].label)); memcpy(list[element].label, data + i, len - 3); i += len - 3; list[element].ctr = data[i++]; } else { i += len; } element++; } else { if (state->verbose) { fprintf(stderr, "Unexpected tag returned on list\n"); } return YKHSMAUTHR_GENERIC_ERROR; } } *list_items = element; if (i != recv_len) { return YKHSMAUTHR_GENERIC_ERROR; } return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_get_challenge(ykhsmauth_state *state, const char *label, uint8_t *challenge, size_t *challenge_len) { return ykhsmauth_get_challenge_ex(state, label, NULL, 0, challenge, challenge_len); } ykhsmauth_rc ykhsmauth_get_challenge_ex(ykhsmauth_state *state, const char *label, const uint8_t *cpw, size_t cpw_len, uint8_t *challenge, size_t *challenge_len) { if (state == NULL || label == NULL || cpw_len > YKHSMAUTH_PW_LEN || strlen(label) < YKHSMAUTH_MIN_LABEL_LEN || strlen(label) > YKHSMAUTH_MAX_LABEL_LEN || challenge == NULL || challenge_len == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_GET_CHALLENGE, 0, 0, 0, {0}}}; add_tag(&apdu, YKHSMAUTH_TAG_LABEL, label, strlen(label), 0); if(cpw && cpw_len) { add_tag(&apdu, YKHSMAUTH_TAG_PW, cpw, cpw_len, YKHSMAUTH_PW_LEN - cpw_len); } unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to get challenge: %04x\n", sw); } return translate_error(sw, NULL); } if (*challenge_len < recv_len) { return YKHSMAUTHR_INVALID_PARAMS; } *challenge_len = recv_len; memcpy(challenge, data, recv_len); return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_get_pubkey(ykhsmauth_state *state, const char *label, uint8_t *pubkey, size_t *pubkey_len) { if (state == NULL || label == NULL || strlen(label) < YKHSMAUTH_MIN_LABEL_LEN || strlen(label) > YKHSMAUTH_MAX_LABEL_LEN || pubkey == NULL || pubkey_len == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_GET_PUBKEY, 0, 0, 0, {0}}}; add_tag(&apdu, YKHSMAUTH_TAG_LABEL, label, strlen(label), 0); unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to get pubkey: %04x\n", sw); } return translate_error(sw, NULL); } if (*pubkey_len < recv_len) { return YKHSMAUTHR_INVALID_PARAMS; } *pubkey_len = recv_len; memcpy(pubkey, data, recv_len); return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_get_mgmkey_retries(ykhsmauth_state *state, uint8_t *retries) { if (state == NULL || retries == NULL) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_GET_MGMKEY_RETRIES, 0, 0, 0, {0}}}; unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to get Management key retries: %04x\n", sw); } return translate_error(sw, NULL); } *retries = data[0]; return YKHSMAUTHR_SUCCESS; } ykhsmauth_rc ykhsmauth_put_mgmkey(ykhsmauth_state *state, uint8_t *mgmkey, size_t mgmkey_len, uint8_t *new_mgmkey, size_t new_mgmkey_len, uint8_t *retries) { if (state == NULL || mgmkey == NULL || mgmkey_len != YKHSMAUTH_PW_LEN || new_mgmkey == NULL || new_mgmkey_len != YKHSMAUTH_PW_LEN) { return YKHSMAUTHR_INVALID_PARAMS; } APDU apdu = {{0, YKHSMAUTH_INS_PUT_MGMKEY, 0, 0, 0, {0}}}; add_tag(&apdu, YKHSMAUTH_TAG_MGMKEY, mgmkey, mgmkey_len, 0); add_tag(&apdu, YKHSMAUTH_TAG_MGMKEY, new_mgmkey, new_mgmkey_len, 0); unsigned char data[256] = {0}; DWORD recv_len = sizeof(data); uint16_t sw = 0; ykhsmauth_rc rc = send_data(state, &apdu, data, &recv_len, &sw); if (rc != YKHSMAUTHR_SUCCESS) { return rc; } else if (sw != SW_SUCCESS) { if (state->verbose) { fprintf(stderr, "Unable to store Management key: %04x\n", sw); } return translate_error(sw, retries); } return YKHSMAUTHR_SUCCESS; } yubihsm-shell-2.6.0/ykhsmauth/README.adoc0000644000175100001770000000063014666527773017501 0ustar runnerdocker== YkHSMAuth Library The YkHSMAuth C Library `libykhsmauth` is a native library to interact with the HSM auth application on a YubiKey. This application is meant to be used for having the HSM authentication keys on a YubiKey. The library exposes functions in the `ykhsmauth_` namespace. These all interact with the HSM auth application over PCSC and are meant for management and usage for the application. yubihsm-shell-2.6.0/ykhsmauth/version.rc.in0000644000175100001770000000210714666527773020335 0ustar runnerdocker #include #define VER_FILEVERSION @yubihsm_shell_VERSION_MAJOR@,@yubihsm_shell_VERSION_MINOR@,@yubihsm_shell_VERSION_PATCH@,0 #define VER_FILEVERSION_STR "@yubihsm_shell_VERSION_MAJOR@.@yubihsm_shell_VERSION_MINOR@.@yubihsm_shell_VERSION_PATCH@.0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_FILEVERSION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Yubico AB" VALUE "FileDescription", "YubiAuth Interface Library" VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "ykhsmauth.dll" VALUE "LegalCopyright", "\xa9 Yubico AB" VALUE "OriginalFilename", "ykhsmauth.dll" VALUE "ProductName", "YubiHSM" VALUE "ProductVersion", VER_FILEVERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END yubihsm-shell-2.6.0/ykhsmauth/error.c0000644000175100001770000000400314666527773017207 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "ykhsmauth.h" #include #define ERR(name, desc) \ { name, #name, desc } typedef struct { ykhsmauth_rc rc; const char *name; const char *description; } err_t; static const err_t errors[] = { ERR(YKHSMAUTHR_SUCCESS, "Successful return"), ERR(YKHSMAUTHR_MEMORY_ERROR, "Device memory error"), ERR(YKHSMAUTHR_PCSC_ERROR, "Error in PCSC call"), ERR(YKHSMAUTHR_GENERIC_ERROR, "General device error"), ERR(YKHSMAUTHR_WRONG_PW, "Wrong Password/Authentication key"), ERR(YKHSMAUTHR_INVALID_PARAMS, "Invalid argument to a device command"), ERR(YKHSMAUTHR_ENTRY_NOT_FOUND, "Entry not found"), ERR(YKHSMAUTHR_STORAGE_FULL, "Device storage full"), ERR(YKHSMAUTHR_TOUCH_ERROR, "Device not touched"), ERR(YKHSMAUTHR_ENTRY_INVALID, "Entry invalid"), ERR(YKHSMAUTHR_DATA_INVALID, "Invalid authentication data"), ERR(YKHSMAUTHR_NOT_SUPPORTED, "Device command not supported"), }; const char *ykhsmauth_strerror(ykhsmauth_rc err) { static const char *unknown = "Unknown ykhsmauth error"; const char *p; if (-err < 0 || -err >= (int) (sizeof(errors) / sizeof(errors[0]))) { return unknown; } p = errors[-err].description; if (!p) { p = unknown; } return p; } const char *ykhsmauth_strerror_name(ykhsmauth_rc err) { if (-err < 0 || -err >= (int) (sizeof(errors) / sizeof(errors[0]))) { return NULL; } return errors[-err].name; } yubihsm-shell-2.6.0/resources/0000755000175100001770000000000014666527773015712 5ustar runnerdockeryubihsm-shell-2.6.0/resources/tests/0000755000175100001770000000000014666527773017054 5ustar runnerdockeryubihsm-shell-2.6.0/resources/tests/bash/0000755000175100001770000000000014666527773017771 5ustar runnerdockeryubihsm-shell-2.6.0/resources/tests/bash/cmdline_test.sh0000755000175100001770000002154714666527773023013 0ustar runnerdocker#!/bin/bash if [ "$#" -eq 1 ]; then BIN=$1 # path to the yubihsm-shell command line tool - using default connector elif [ "$#" -gt 1 ]; then BIN="$1 -C $2" # path to the yubihsm-shell command line tool - using specified connector else BIN="yubihsm-shell" fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e test "$BIN --version" "yubihsm-shell --version" test "$BIN --help" "yubihsm-shell --help" test "$BIN -a get-device-info | grep \"Serial number:\"" "yubihsm-shell -a get-device-info" echo "********************************************************** " echo " Reset YubiHSM" echo "********************************************************** " test "$BIN -p password -a reset" sleep 3 echo "********************************************************** " echo " Blink" echo "********************************************************** " test "$BIN -p password -a blink" "-a blink" test "$BIN -p password -a blink --duration=5" "-a blink --duration=5" test "$BIN -p password -a blink-device" "blink-device" test "$BIN -p password -a blink-device --duration=5" "-a blink-device --duration=5" echo "********************************************************** " echo " Get Pseudo-random" echo "********************************************************** " test "$BIN -p password -a get-pseudo-random | wc -c | grep 513" "get-pseudo-random" # includes a new line test "$BIN -p password -a get-pseudo-random --out=random.txt" get-pseudo-random --out=random.txt length=$(cat random.txt | wc -c) if [ $length -ne 512 ]; then echo "Expected 512 but was $length characters. Without specifying byte count, 256 bytes (=512 characters) pseudo random number should have been produced." exit 1; fi rm random.txt test "$BIN -p password -a get-pseudo-random --count=10 | wc -c | grep 21" "get-pseudo-random --count=10" # includes a new line test "$BIN -p password -a get-pseudo-random --count=10 --out=random.txt" "get-pseudo-random --count=10 --out=random.txt" length=$(cat random.txt | wc -c) if [ $length -ne 20 ]; then echo "Expected 20 but was $length characters." exit 1; fi rm random.txt echo "********************************************************** " echo " Asymmetric Keys" echo "********************************************************** " ./test_edkey.sh "$BIN" if [ -z ${DOCKER_IMAGE} ] || [ ${DOCKER_IMAGE} != "centos:7" ]; then # This DOCKER_IMAGE environment variable is set in the build_and_test.yml github workflow. ./test_eckey.sh "$BIN" fi ./test_rsakey.sh "$BIN" echo "********************************************************** " echo " HMAC Keys" echo "********************************************************** " ./test_hmackey.sh "$BIN" echo "********************************************************** " echo " AEAD Keys" echo "********************************************************** " ./test_otpaeadkey.sh "$BIN" echo "********************************************************** " echo " Template" echo "********************************************************** " test "$BIN -p password -a get-pseudo-random --count=512 --out=template.txt" " Generate 512 pseudo random bytes" test_with_resp "$BIN -p password -a put-template -i 0 -l template -d 1 -A template-ssh --in template.txt" " Import template" id=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $id -t template" " Get object info" info=$($BIN -p password -a get-object-info -i $id -t template 2> /dev/null) test "echo $info | grep \"id: $id\"" " Object info contains correct ID" test "echo $info | grep \"type: template\"" " Object info contains correct type" test "echo $info | grep \"algorithm: template-ssh\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"template\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1\"" " Object info contains correct domains" test "echo $info | grep \"origin: imported\"" " Object info contains correct origin" test "$BIN -p password -a get-template -i $id" " Get template" test "$BIN -p password -a delete-object -i $id -t template" " Delete template" rm resp.txt rm template.txt echo "********************************************************** " echo " Wrap Keys" echo "********************************************************** " ./test_wrapkey.sh "$BIN" echo "********************************************************** " echo " List Objects" echo "********************************************************** " test "$BIN -p password -a generate-asymmetric-key -i 100 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecp224" " Generate EC key for testing" test "$BIN -p password -a list-objects -A any -t any -i 100 | grep \"Found 1 object(s)\"" " List objects by ID" test "$BIN -p password -a list-objects -A any -t asymmetric-key | grep \"Found 1 object(s)\"" " List objects by type" test "$BIN -p password -a list-objects -A any -t any -d 5,8,13 | grep \"Found 2 object(s)\"" " List objects by domain" test "$BIN -p password -a list-objects -A any -t any -c sign-ecdsa,derive-ecdh,sign-attestation-certificate | grep \"Found 2 object(s)\"" " List objects by capabilities" test "$BIN -p password -a list-objects -A ecp224 -t any | grep \"Found 1 object(s)\"" " List objects by algorithm" test "$BIN -p password -a list-objects -A any -t any -l ecKey | grep \"Found 1 object(s)\"" " List objects by label" test "$BIN -p password -a delete-object -i 100 -t asymmetric-key" " Delete key" echo "********************************************************** " echo " Label Size" echo "********************************************************** " # Label 0 chars test "$BIN -p password -a generate-asymmetric-key -i 300 -d 5,8,13 -c sign-ecdsa -A ecp224" " Create key with no label" test "$BIN -p password -a get-object-info -i 300 -t asymmetric-key | grep 'label: \"\"'" " Object info contains empty label" #$BIN -p password -a list-objects -A any -t any -l "" | grep "Found 1 object(s)" # Label 39 chars test "$BIN -p password -a generate-asymmetric-key -i 200 -l abcdefghijklmnopqrstuvwxyz0123456789abc -d 5,8,13 -c sign-ecdsa -A ecp224" " Create object with 39 characters label" test "$BIN -p password -a get-object-info -i 200 -t asymmetric-key | grep 'label: \"abcdefghijklmnopqrstuvwxyz0123456789abc\"'" " Object info contains correct lable with 39 characters" test "$BIN -p password -a list-objects -A any -t any -l abcdefghijklmnopqrstuvwxyz0123456789abc | grep \"Found 1 object(s)\"" " list-objects found object with 39 characters" # Label 40 chars test "$BIN -p password -a generate-asymmetric-key -i 100 -l abcdefghijklmnopqrstuvwxyz0123456789abcd -d 5,8,13 -c sign-ecdsa -A ecp224" " Create object with 40 characters label" test "$BIN -p password -a get-object-info -i 100 -t asymmetric-key | grep 'label: \"abcdefghijklmnopqrstuvwxyz0123456789abcd\"'" " Object info contains correct lable with 40 characters" test "$BIN -p password -a list-objects -A any -t any -l abcdefghijklmnopqrstuvwxyz0123456789abcd | grep \"Found 1 object(s)\"" " list-objects found object with 40 characters" # Label 41 chars (set +e; $BIN -p password -a generate-asymmetric-key -i 400 -l "abcdefghijklmnopqrstuvwxyz0123456789abcde" -d "5,8,13" -c "sign-ecdsa" -A "ecp224"; true) 2>&1 >/dev/null | grep "Failed to generate asymmetric key: Invalid argument to a function" # Label doesn't exist test "$BIN -p password -a list-objects -A any -t any -l doesnotexist | grep \"Found 0 object(s)\"" " List objects by label that does not exist" test "$BIN -p password -a delete-object -i 100 -t asymmetric-key" " Clean up" test "$BIN -p password -a delete-object -i 200 -t asymmetric-key" " Clean up" test "$BIN -p password -a delete-object -i 300 -t asymmetric-key" " Clean up" echo "********************************************************** " echo " Authentication Keys" echo "********************************************************** " test_with_resp "$BIN -p password -a put-authentication-key -i 0 -l authkey -d 1,2,3 -c all --delegated all --new-password foo123" " Create new authentication key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN --authkey $keyid -p foo123 -a get-object-info -i 1 -t authentication-key" " Login using new authetication key" test "$BIN -p password -a delete-object -i $keyid -t authentication-key" " Delete new authentication key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.6.0/resources/tests/bash/test_otpaeadkey.sh0000755000175100001770000000646614666527773023531 0ustar runnerdocker#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e echo "====================== AEAD keys ===================== " echo "------------- AEAD Key 128" test_with_resp "$BIN -p password -a generate-otp-aead-key -i 0 -l aeadkey -d 1,2,3 -c randomize-otp-aead -A aes128-yubico-otp --nonce 0x01020304" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $5}') test "$BIN -p password -a get-object-info -i $keyid -t otp-aead-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t otp-aead-key 2> /dev/null) test "echo $info | grep \"id: $keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: otp-aead-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: aes128-yubico-otp\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"aeadkey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1:2:3\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: randomize-otp-aead\"" " Object info contains correct capabilities" test "$BIN -p password -a randomize-otp-aead -i $keyid" " Randomize OTP AEAD" test "$BIN -p password -a delete-object -i $keyid -t otp-aead-key" " Delete key" echo "------------- AEAD Key 128" test_with_resp "$BIN -p password -a generate-otp-aead-key -i 0 -l aeadkey -d 1,2,3 -c randomize-otp-aead -A aes192-yubico-otp --nonce 0x01020304" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $5}') test "$BIN -p password -a get-object-info -i $keyid -t otp-aead-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t otp-aead-key 2> /dev/null) test "echo $info | grep \"algorithm: aes192-yubico-otp\"" " Object info contains correct algorithm" test "$BIN -p password -a randomize-otp-aead -i $keyid" " Randomize OTP AEAD" test "$BIN -p password -a delete-object -i $keyid -t otp-aead-key" " Delete key" echo "------------- AEAD Key 256" test_with_resp "$BIN -p password -a generate-otp-aead-key -i 0 -l aeadkey -d 1,2,3 -c randomize-otp-aead -A aes256-yubico-otp --nonce 0x01020304" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $5}') test "$BIN -p password -a get-object-info -i $keyid -t otp-aead-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t otp-aead-key 2> /dev/null) test "echo $info | grep \"algorithm: aes256-yubico-otp\"" " Object info contains correct algorithm" test "$BIN -p password -a randomize-otp-aead -i $keyid" " Randomize OTP AEAD" test "$BIN -p password -a delete-object -i $keyid -t otp-aead-key" " Delete key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.6.0/resources/tests/bash/test_x509template.pem0000644000175100001770000000172514666527773024001 0ustar runnerdocker-----BEGIN CERTIFICATE----- MIICpzCCAY+gAwIBAgIRALnaMgizd13cmPh34E4HNz0wDQYJKoZIhvcNAQELBQAw KjEoMCYGA1UEAwwfWXViaUhTTTIgQXR0ZXN0YXRpb24gKDEzMjAwNTAxKTAgFw0x NzAxMDEwMDAwMDBaGA8yMDcxMTAwNTAwMDAwMFowKDEmMCQGA1UEAwwdWXViaUhT TSBBdHRlc3RhdGlvbiBpZDoweDU2MGQwTjAQBgcqhkjOPQIBBgUrgQQAIQM6AATn 8QLCgsBZlpkoqdMOTbWS/tOiXfI1aOMrUQC+w6rWw8WwEbJ7LjqoPwdWg0DKrXeA 7sAEMUKX4aOBnTCBmjATBgorBgEEAYLECgQBBAUEAwIBAzAUBgorBgEEAYLECgQC BAYCBADJbHUwEgYKKwYBBAGCxAoEAwQEAwIAATATBgorBgEEAYLECgQEBAUDAwAQ kDAZBgorBgEEAYLECgQFBAsDCQAAAAAEAAAIgDASBgorBgEEAYLECgQGBAQCAlYN MBUGCisGAQQBgsQKBAkEBwwFZWNLZXkwDQYJKoZIhvcNAQELBQADggEBAEV/0jl7 ulAmLLiYGV8ELoavjtJ3wmMLyJpSURC8WPO8MucAopIsh0URXKpjLjHQHqscdAbP DyT+/l1VfFS7Fvsz/OXeMP1dYzpoYzw4iyHFkvf5G8k0hxY+BEqBa89MXKGrcDo0 iu0lSusaEJF2zq3PH3hnPIXm9SJDfWcZ7iueA0xGu6miUz3rHklnbPUqaM/omGyV MgAtLOolX7rnW7E3MEkAOII1kbwv8C/NlseKXyECRvAn2reAMH11c/t2BvGMbD81 OGTPZ2OvfNJcPnzy1olxE0Ajew5CrOB2XrOaqhVrNPA4aqpCT3ukMv60m6TXsHnU RdEhPSf0SomH7MQ= -----END CERTIFICATE----- yubihsm-shell-2.6.0/resources/tests/bash/test_wrapkey.sh0000755000175100001770000005677214666527773023072 0ustar runnerdocker#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } cmp_str_content () { set +e if [[ $1 == *"$2"* ]]; then echo " $3 in object info ... OK!" else echo "Wrong $3" echo $1 exit 1 fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e test "$BIN -p password -a reset" " Reset device" sleep 3 eckey=100 aeskey=200 test "$BIN -p password -a generate-asymmetric-key -i $eckey -l eckey -d 1 -c exportable-under-wrap,sign-ecdsa -A ecp224" " Generate EC Key to wrap" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 0" "Sequence" cmp_str_content "$info" "origin: generated" "Origin" echo "**********************************" echo " aes128-ccm-wrap" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap -A aes128-ccm-wrap" " Generate wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes128-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 24" "Length" echo "=== Import key" test_with_resp "$BIN -p password -a get-pseudo-random --count 16" " Get random 16 bytes" wrapkey=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a put-wrap-key -i 0 -l imported_wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap --in=$wrapkey" " Import wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes128-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 24" "Length" cmp_str_content "$info" "origin: imported" "Origin" echo "=== Wrap and unwrap objects with generated wrap key" test "$BIN -p password -a get-wrapped --wrap-id $keyid -i 100 -t asymmetric-key --out key.gen_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $keyid --in key.gen_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 1" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Wrap and unwrap objects with imported wrap key" test "$BIN -p password -a get-wrapped --wrap-id $import_keyid -i 100 -t asymmetric-key --out key.imp_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $import_keyid --in key.imp_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 2" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported wrap key" rm key.gen_wrapped rm key.imp_wrapped echo "**********************************" echo " aes192-ccm-wrap" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap -A aes192-ccm-wrap" " Generate wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes192-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 32" "Length" echo "=== Import key" test_with_resp "$BIN -p password -a get-pseudo-random --count 24" " Get random 16 bytes" wrapkey=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a put-wrap-key -i 0 -l imported_wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap --in=$wrapkey" " Import wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes192-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 32" "Length" cmp_str_content "$info" "origin: imported" "Origin" echo "=== Wrap and unwrap objects with generated wrap key" test "$BIN -p password -a get-wrapped --wrap-id $keyid -i 100 -t asymmetric-key --out key.gen_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $keyid --in key.gen_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 3" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Wrap and unwrap objects with imported wrap key" test "$BIN -p password -a get-wrapped --wrap-id $import_keyid -i 100 -t asymmetric-key --out key.imp_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $import_keyid --in key.imp_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 4" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported wrap key" rm key.gen_wrapped rm key.imp_wrapped echo "**********************************" echo " aes256-ccm-wrap" echo "**********************************" echo "=== Generate key" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap -A aes256-ccm-wrap" " Generate wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes256-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 40" "Length" echo "=== Import key" test_with_resp "$BIN -p password -a get-pseudo-random --count 32" " Get random 16 bytes" wrapkey=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a put-wrap-key -i 0 -l imported_wrapkey -d 1 -c export-wrapped,import-wrapped --delegated sign-ecdsa,exportable-under-wrap --in=$wrapkey" " Import wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: aes256-ccm-wrap" "Algorithm" cmp_str_content "$info" "length: 40" "Length" cmp_str_content "$info" "origin: imported" "Origin" echo "=== Wrap and unwrap objects with generated wrap key" test "$BIN -p password -a get-wrapped --wrap-id $keyid -i 100 -t asymmetric-key --out key.gen_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $keyid --in key.gen_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 5" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Wrap and unwrap objects with imported wrap key" test "$BIN -p password -a get-wrapped --wrap-id $import_keyid -i 100 -t asymmetric-key --out key.imp_wrapped" " Wrap EC key" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-wrapped --wrap-id $import_keyid --in key.imp_wrapped" " Wrap EC key" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) cmp_str_content "$info" "sequence: 6" "Sequence" cmp_str_content "$info" "origin: generated:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped key" echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported wrap key" rm key.gen_wrapped rm key.imp_wrapped device_info=$($BIN -p password -a get-device-info 2> /dev/null) if [[ "$device_info" != *"aes-kwp"* ]]; then test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" exit 0 fi aes_enabled=false if [[ "$device_info" == *"aes-cbc"* ]]; then aes_enabled=true test "$BIN -p password -a generate-symmetric-key -i $aeskey -l aeskey -d 1 -c exportable-under-wrap,encrypt-cbc,decrypt-cbc -A aes128" " Generate AES Key to wrap" test_with_resp "$BIN -p password -a get-pseudo-random --count 16" " Get random 16 bytes for IV" iv=$(tail -1 resp.txt | awk '{print $0}') test_with_resp "$BIN -p password -a get-pseudo-random --count 32" " Get random 32 bytes to test encryption" data=$(tail -1 resp.txt | awk '{print $0}') fi RSA_KEYSIZE=("2048" "3072" "4096") seq_ec=6 seq_aes=0 for k in ${RSA_KEYSIZE[@]}; do echo "**********************************" echo " RSA$k" echo "**********************************" echo "=== Generate RSA wrap keys" test_with_resp "$BIN -p password -a generate-wrap-key -i 0 -l wrapkey -c import-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc -A rsa$k" " Generate RSA wrap key" keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: rsa$k" "Algorithm" cmp_str_content "$info" "origin: generated" "Origin" test "$BIN -p password -a get-public-key -i $keyid -t wrap-key --out public_wrapkey.pem" " Export rsa public wrap key" test "$BIN -p password -a put-public-wrapkey -i $keyid -c export-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in public_wrapkey.pem" " Import RSA public wrap key" rm public_wrapkey.pem echo "=== Wrap and unwrap EC object with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $keyid -i $eckey -t asymmetric-key --out rsawrapped.object" " Export wrapped EC object" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $keyid --in rsawrapped.object" " Import wrapped EC object" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.object echo "=== Wrap and unwrap EC key material with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $keyid -i $eckey -t asymmetric-key --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --out rsawrapped.key" " Export wrapped EC key material" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $keyid -i $eckey -t asymmetric-key -A ecp224 -c exportable-under-wrap,sign-ecdsa --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --in rsawrapped.key" " Import wrapped EC key material" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.key if [[ "$aes_enabled" = true ]]; then echo "=== Wrap and unwrap AES object with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $keyid -i $aeskey -t symmetric-key --out rsawrapped.object" " Export wrapped AES object" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $keyid --in rsawrapped.object" " Import wrapped AES object" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.object rm data.enc echo "=== Wrap and unwrap AES key material with generated RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $keyid -i $aeskey -t symmetric-key --oaep rsa-oaep-sha384 --mgf1 mgf1-sha1 --out rsawrapped.key" " Export wrapped AES key material" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $keyid -i $aeskey -t symmetric-key -A aes128 -c exportable-under-wrap,decrypt-cbc,encrypt-cbc --oaep rsa-oaep-sha384 --mgf1 mgf1-sha1 --in rsawrapped.key" " Import wrapped AES key material" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.key rm data.enc fi echo "=== Import RSA wrap keys" test "openssl genrsa -out keypair.pem $k" " Generate RSA key with OpenSSL" test "openssl rsa -in keypair.pem -pubout -out key.pub" " Extract public key from OpenSSL generated keypair" test_with_resp "$BIN -p password -a put-rsa-wrapkey -i 0 -d 1 -c import-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in keypair.pem" " Import RSA wrap key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') info=$($BIN -p password -a get-object-info -i $import_keyid -t wrap-key 2> /dev/null) cmp_str_content "$info" "algorithm: rsa$k" "Algorithm" cmp_str_content "$info" "origin: imported" "Origin" test "$BIN -p password -a put-public-wrapkey -i $import_keyid -c export-wrapped --delegated exportable-under-wrap,sign-ecdsa,encrypt-cbc,decrypt-cbc --in key.pub" " Import RSA public wrap key" rm keypair.pem rm key.pub echo "=== Wrap and unwrap EC object with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $import_keyid -i $eckey -t asymmetric-key --out rsawrapped.object" " Export wrapped EC object" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $import_keyid --in rsawrapped.object" " Import wrapped EC object" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.object echo "=== Wrap and unwrap EC key material with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $import_keyid -i $eckey -t asymmetric-key --oaep rsa-oaep-sha512 --mgf1 mgf1-sha512 --out rsawrapped.key" " Export wrapped EC key material" test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $import_keyid -i $eckey -t asymmetric-key -A ecp224 -c exportable-under-wrap,sign-ecdsa --oaep rsa-oaep-sha512 --mgf1 mgf1-sha512 --in rsawrapped.key" " Import wrapped EC key material" info=$($BIN -p password -a get-object-info -i $eckey -t asymmetric-key 2> /dev/null) seq_ec=$((seq_ec+1)) cmp_str_content "$info" "sequence: $seq_ec" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: exportable-under-wrap:sign-ecdsa" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" rm rsawrapped.key if [[ "$aes_enabled" = true ]]; then echo "=== Wrap and unwrap AES object with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped --wrap-id $import_keyid -i $aeskey -t symmetric-key --out rsawrapped.object" " Export wrapped AES object" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped --wrap-id $import_keyid --in rsawrapped.object" " Import wrapped AES object" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.object rm data.enc echo "=== Wrap and unwrap AES key material with imported RSA wrap key" test "$BIN -p password -a get-rsa-wrapped-key --wrap-id $import_keyid -i $aeskey -t symmetric-key --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --out rsawrapped.key" " Export wrapped AES key material" test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" test "$BIN -p password -a put-rsa-wrapped-key --wrap-id $import_keyid -i $aeskey -t symmetric-key -A aes128 -c exportable-under-wrap,decrypt-cbc,encrypt-cbc --oaep rsa-oaep-sha1 --mgf1 mgf1-sha384 --in rsawrapped.key" " Import wrapped AES key material" info=$($BIN -p password -a get-object-info -i $aeskey -t symmetric-key 2> /dev/null) seq_aes=$((seq_aes+1)) cmp_str_content "$info" "sequence: $seq_aes" "Sequence" cmp_str_content "$info" "origin: imported:imported_wrapped" "Origin" cmp_str_content "$info" "capabilities: decrypt-cbc:encrypt-cbc:exportable-under-wrap" "Capabilities" test "$BIN -p password -a sign-ecdsa -i $eckey -A ecdsa-sha1 --in data.txt" " Perform signature with imported wrapped EC key" test "$BIN -p password -a encrypt-aescbc -i $aeskey --iv $iv --in $data --out data.enc" " Perform encryption with imported wrapped AES key" test_with_resp "$BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc" " Perform decryption with imported wrapped AES key" data_dec=$(tail -1 resp.txt | awk '{print $0}') if [[ "$data" == "$data_dec" ]]; then echo " Compare decrypted data to plain text ... OK!" else $BIN -p password -a decrypt-aescbc -i $aeskey --iv $iv --in data.enc --out data.dec exit fi rm rsawrapped.key rm data.enc fi echo "=== Clean up" test "$BIN -p password -a delete-object -i $keyid -t wrap-key" " Delete generated RSA wrap key" test "$BIN -p password -a delete-object -i $keyid -t public-wrap-key" " Delete generated RSA public wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t wrap-key" " Delete imported RSA wrap key" test "$BIN -p password -a delete-object -i $import_keyid -t public-wrap-key" " Delete imported RSA public wrap key" done #test "$BIN -p password -a delete-object -i $eckey -t asymmetric-key" " Delete EC key" #if [[ "$aes_enabled" = true ]]; then # test "$BIN -p password -a delete-object -i $aeskey -t symmetric-key" " Delete AES key" #fi test "$BIN -p password -a reset" " Reset device" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.6.0/resources/tests/bash/test_rsakey.sh0000755000175100001770000007123314666527773022673 0ustar runnerdocker#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing and decryption data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e echo "====================== RSA keys ===================== " echo "------------- RSA2048" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l rsaKey -d 1 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate -A rsa2048" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t asymmetric-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: rsa2048\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"rsaKey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss\"" " Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey_rsa2048.pem" " Get public key" echo "Import key:" test "openssl genrsa -out rsa2048-keypair.pem 2048" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l rsaKeyImport -d 2 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate --in=rsa2048-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key" " Get object info" info=$($BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $import_keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: rsa2048\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"rsaKeyImport\"'" " Object info contains correct label" test "echo $info | grep \"domains: 2\"" " Object info contains correct domains" test "echo $info | grep \"origin: imported\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss\"" " Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_rsa2048_imported.pem" " Get public key" echo "Signing with generated key:" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.2048pkcs1sha1gen.sig" " Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa2048.pem -signature data.2048pkcs1sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.2048pkcs1sha256gen.sig" " Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa2048.pem -signature data.2048pkcs1sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.2048pkcs1sha384gen.sig" " Sign with rsa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa2048.pem -signature data.2048pkcs1sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.2048pkcs1sha512gen.sig" " Sign with rsa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa2048.pem -signature data.2048pkcs1sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.2048psssha1gen.sig" " Sign with rsa-pss-sha1" #test "openssl dgst -sha1 -verify pubkey_rsa2048.pem -signature data.2048psssha1gen.sig data.txt" " Verify signature with OpenSSL" #test "openssl pkeyutl -verify -in data.txt -sigfile data.2048psssha1gen.sig -pkeyopt rsa_padding_mode:pss -pubin -inkey pubkey_rsa2048.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha1" " verify" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.2048psssha256gen.sig" " Sign with rsa-pss-sha256" #test "openssl dgst -sha256 -verify pubkey_rsa2048.pem -signature data.2048psssha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.2048psssha384gen.sig" " Sign with rsa-pss-sha384" #test "openssl dgst -sha384 -verify pubkey_rsa2048.pem -signature data.2048psssha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.2048psssha512gen.sig" " Sign with rsa-pss-sha512" #test "openssl dgst -sha512 -verify pubkey_rsa2048.pem -signature data.2048psssha512gen.sig data.txt" " Verify signature with OpenSSL" echo "Signing with imported key:" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.2048pkcs1sha1import.sig" " Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa2048_imported.pem -signature data.2048pkcs1sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.2048pkcs1sha256import.sig" " Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa2048_imported.pem -signature data.2048pkcs1sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.2048pkcs1sha384import.sig" " Sign with rsa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa2048_imported.pem -signature data.2048pkcs1sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.2048pkcs1sha512import.sig" " Sign with rsa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa2048_imported.pem -signature data.2048pkcs1sha512import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.2048psssha1import.sig" " Sign with rsa-pss-sha1" #test "openssl dgst -sha1 -verify pubkey_rsa2048_imported.pem -signature data.2048psssha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.2048psssha256import.sig" " Sign with rsa-pss-sha256" #test "openssl dgst -sha256 -verify pubkey_rsa2048_imported.pem -signature data.2048psssha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.2048psssha384import.sig" " Sign with rsa-pss-sha384" #test "openssl dgst -sha384 -verify pubkey_rsa2048_imported.pem -signature data.2048psssha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.2048psssha512import.sig" " Sign with rsa-pss-sha512" #test "openssl dgst -sha512 -verify pubkey_rsa2048_imported.pem -signature data.2048psssha512import.sig data.txt" " Verify signature with OpenSSL" echo "Make self signed certificate:" set +e $BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 2>&1 > /dev/null # Some YubiHSMs does not have default attestation certificate def_attestation=$? set -e if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Decrypt with generated key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa2048.pem -pubin -in data.txt -out data.enc" " Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec" " Decrypt with yubihsm-shell" test "cmp data.txt data.dec" " Compare decrypted data with plain text data" test "rm data.dec" " Clean up" echo "Decrypt with imported key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa2048_imported.pem -pubin -in data.txt -out data.enc" " Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec" " Decrypt with yubihsm-shell" test "cmp data.txt data.dec" " Compare decrypted data with plain text data" test "rm data.dec" " Clean up" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" echo "------------- RSA3072" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l rsaKey -d 1 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate -A rsa3072" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t asymmetric-key" " Get object info" test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey_rsa3072.pem" " Get public key" echo "Import key:" test "openssl genrsa -out rsa3072-keypair.pem 3072" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l rsaKeyImport -d 2 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate --in=rsa3072-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key" " Get object info" test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_rsa3072_imported.pem" " Get public key" echo "Signing with generated key:" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.3072pkcs1sha1gen.sig" " Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa3072.pem -signature data.3072pkcs1sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.3072pkcs1sha256gen.sig" " Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa3072.pem -signature data.3072pkcs1sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.3072pkcs1sha384gen.sig" " Sign with sa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa3072.pem -signature data.3072pkcs1sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.3072pkcs1sha512gen.sig" " Sign with sa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa3072.pem -signature data.3072pkcs1sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.3072psssha1gen.sig" " Sign with rsa-pss-sha1" #test "openssl dgst -sha1 -verify pubkey_rsa3072.pem -signature data.3072psssha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.3072psssha256gen.sig" " Sign with rsa-pss-sha256" #test "openssl dgst -sha256 -verify pubkey_rsa3072.pem -signature data.3072psssha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.3072psssha384gen.sig" " Sign with rsa-pss-sha384" #test "openssl dgst -sha384 -verify pubkey_rsa3072.pem -signature data.3072psssha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.3072psssha512gen.sig" " Sign with rsa-pss-sha512" #test "openssl dgst -sha512 -verify pubkey_rsa3072.pem -signature data.3072psssha512gen.sig data.txt" " Verify signature with OpenSSL" echo "Signing with imported key:" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.3072pkcs1sha1import.sig" " Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa3072_imported.pem -signature data.3072pkcs1sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.3072pkcs1sha256import.sig" " Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa3072_imported.pem -signature data.3072pkcs1sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.3072pkcs1sha384import.sig" " Sign with rsa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa3072_imported.pem -signature data.3072pkcs1sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.3072pkcs1sha512import.sig" " Sign with rsa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa3072_imported.pem -signature data.3072pkcs1sha512import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.3072psssha1import.sig" " Sign with rsa-pss-sha1" #test "openssl dgst -sha1 -verify pubkey_rsa3072_imported.pem -signature data.3072psssha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.3072psssha256import.sig" " Sign with rsa-pss-sha256" #test "openssl dgst -sha256 -verify pubkey_rsa3072_imported.pem -signature data.3072psssha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.3072psssha384import.sig" " Sign with rsa-pss-sha384" #test "openssl dgst -sha384 -verify pubkey_rsa3072_imported.pem -signature data.3072psssha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.3072psssha512import.sig" " Sign with rsa-pss-sha512" #test "openssl dgst -sha512 -verify pubkey_rsa3072_imported.pem -signature data.3072psssha512import.sig data.txt" " Verify signature with OpenSSL" echo "Make self signed certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Decrypt with generated key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa3072.pem -pubin -in data.txt -out data.enc" " Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec" " Decrypt with yubihsm-shell" test "cmp data.txt data.dec" " Compare decrypted data with plain text data" test "rm data.dec" " Clean up" echo "Decrypt with imported key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa3072_imported.pem -pubin -in data.txt -out data.enc" " Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec" " Decrypt with yubihsm-shell" test "cmp data.txt data.dec" " Compare decrypted data with plain text data" test "rm data.dec" " Clean up" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" echo "------------- 4096" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l rsaKey -d 1 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate -A rsa4096" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t asymmetric-key" " Get object info" test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey_rsa4096.pem" " Get public key" echo "Import key:" test "openssl genrsa -out rsa4096-keypair.pem 4096" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l rsaKeyImport -d 2 -c sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate --in=rsa4096-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key" " Get object info" test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_rsa4096_imported.pem" " Get public key" echo "Signing with generated key:" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.4096pkcs1sha1gen.sig" " Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa4096.pem -signature data.4096pkcs1sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.4096pkcs1sha256gen.sig" " Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa4096.pem -signature data.4096pkcs1sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.4096pkcs1sha384gen.sig" " Sign with rsa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa4096.pem -signature data.4096pkcs1sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.4096pkcs1sha512gen.sig" " Sign with rsa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa4096.pem -signature data.4096pkcs1sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.4096psssha1gen.sig" " Sign with rsa-pss-sha1" #test "openssl dgst -sha1 -verify pubkey_rsa4096.pem -signature data.4096psssha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.4096psssha256gen.sig" " Sign with rsa-pss-sha256" #test "openssl dgst -sha256 -verify pubkey_rsa4096.pem -signature data.4096psssha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.4096psssha384gen.sig" " Sign with rsa-pss-sha384" #test "openssl dgst -sha384 -verify pubkey_rsa4096.pem -signature data.4096psssha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.4096psssha512gen.sig" " Sign with rsa-pss-sha512" #test "openssl dgst -sha512 -verify pubkey_rsa4096.pem -signature data.4096psssha512gen.sig data.txt" " Verify signature with OpenSSL" echo "Signing with imported key:" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --outformat binary --out data.4096pkcs1sha1import.sig" " Sign with rsa-pkcs1-sha1" test "openssl dgst -sha1 -verify pubkey_rsa4096_imported.pem -signature data.4096pkcs1sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --outformat binary --out data.4096pkcs1sha256import.sig" " Sign with rsa-pkcs1-sha256" test "openssl dgst -sha256 -verify pubkey_rsa4096_imported.pem -signature data.4096pkcs1sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --outformat binary --out data.4096pkcs1sha384import.sig" " Sign with rsa-pkcs1-sha384" test "openssl dgst -sha384 -verify pubkey_rsa4096_imported.pem -signature data.4096pkcs1sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --outformat binary --out data.4096pkcs1sha512import.sig" " Sign with rsa-pkcs1-sha512" test "openssl dgst -sha512 -verify pubkey_rsa4096_imported.pem -signature data.4096pkcs1sha512import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.4096psssha1import.sig" " Sign with rsa-pss-sha1" #test "openssl dgst -sha1 -verify pubkey_rsa4096_imported.pem -signature data.4096psssha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.4096psssha256import.sig" " Sign with rsa-pss-sha256" #test "openssl dgst -sha256 -verify pubkey_rsa4096_imported.pem -signature data.4096psssha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.4096psssha384import.sig" " Sign with rsa-pss-sha384" #test "openssl dgst -sha384 -verify pubkey_rsa4096_imported.pem -signature data.4096psssha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.4096psssha512import.sig" " Sign with rsa-pss-sha512" #test "openssl dgst -sha512 -verify pubkey_rsa4096_imported.pem -signature data.4096psssha512import.sig data.txt" " Verify signature with OpenSSL" echo "Make self signed certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Decrypt with generated key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa4096.pem -pubin -in data.txt -out data.enc" " Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec" " Decrypt with yubihsm-shell" test "cmp data.txt data.dec" " Compare decrypted data with plain text data" test "rm data.dec" " Clean up" echo "Decrypt with imported key and PKCS1v15:" test "openssl rsautl -encrypt -inkey pubkey_rsa4096_imported.pem -pubin -in data.txt -out data.enc" " Encryp with OpenSSL" test "$BIN -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec" " Decrypt with yubihsm-shell" test "cmp data.txt data.dec" " Compare decrypted data with plain text data" test "rm data.dec" " Clean up" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" cd .. rm -rf yubihsm-shell_test_dir set +e set +x yubihsm-shell-2.6.0/resources/tests/bash/test_hmackey.sh0000755000175100001770000000720414666527773023013 0ustar runnerdocker#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e echo "====================== HMAC keys ===================== " echo "------------- hmac-sha1" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha1" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"id: $keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: hmac-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: hmac-sha1\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"hmackey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1:2:3\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: sign-hmac\"" " Object info contains correct capabilities" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" echo "------------- hmac-sha256" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha256" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"algorithm: hmac-sha256\"" " Object info contains correct algorithm" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" echo "------------- hmac-sha384" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha384" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"algorithm: hmac-sha384\"" " Object info contains correct algorithm" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" echo "------------- hmac-sha512" test_with_resp "$BIN -p password -a generate-hmac-key -i 0 -l hmackey -d 1,2,3 -c sign-hmac -A hmac-sha512" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t hmac-key" " Get object info" info=$($BIN -p password -a get-object-info -i $keyid -t hmac-key 2> /dev/null) test "echo $info | grep \"algorithm: hmac-sha512\"" " Object info contains correct algorithm" #$BIN -p password -a sign-hmac -i $keyid --in data.txt test "$BIN -p password -a delete-object -i $keyid -t hmac-key" " Delete key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.6.0/resources/tests/bash/test_edkey.sh0000755000175100001770000000520214666527773022467 0ustar runnerdocker#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } set -e echo "====================== ED keys ===================== " # Generate echo "Generate key:" test "$BIN -p password -a generate-asymmetric-key -i 100 -l \"edKey\" -d 1,2,3 -c sign-eddsa -A ed25519" " Generate key" test "$BIN -p password -a get-object-info -i 100 -t asymmetric-key" " get-object-info" info=$($BIN -p password -a get-object-info -i 100 -t asymmetric-key 2>&1) test "echo $info | grep \"id: 0x0064\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: ed25519\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"edKey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 1:2:3\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: sign-eddsa\"" " Object info contains correct capabilities" # Import #ssh-keygen -t ed25519 -C "test@yubihsm.se" -f edkey -N foo123 #$BIN --verbose=5 -p password -a put-asymmetric-key -i 200 -l "edKey_imported" -d "5" -c "sign-eddsa" --in=edkey # Get public key echo "Get public key:" test "$BIN -p password -a get-public-key -i 100" " Get public key to stdout" $BIN -p password -a get-public-key -i 100 > edkey1.pub 2>/dev/null test "$BIN -p password -a get-public-key -i 100 --out edkey2.pub" " Get public key to file" test "cmp edkey1.pub edkey2.pub" " Match public key in stdout and file" # Signing echo "Signing:" test "$BIN -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt" " Sign to stdout" $BIN -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt > data.ed1.sig 2>/dev/null test "$BIN -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt --out data.ed2.sig" " Sign to file" if [[ $(cat data.ed1.sig) != $(cat data.ed2.sig) ]]; then echo "Signature in stdout and file are different" exit 2 fi echo " Matching signature in stdout and file ... OK" # Delete echo "Clean up:" test "$BIN -p password -a delete-object -i 100 -t asymmetric-key" " Delete key" cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.6.0/resources/tests/bash/opensc_test.sh0000755000175100001770000000321114666527773022653 0ustar runnerdocker#!/bin/bash if [ "$#" -ne 1 ]; then echo "Usage: ./opensc_test.sh " echo "" echo "This script expects that YUBIHSM_PKCS11_CONF environment variable is defined" exit fi MODULE=$1 #$env:YUBIHSM_PKCS11_CONF=$YHPKCS11CFG set -e echo "******************* Generation Tests ********************* " pkcs11-tool --module $MODULE --login --pin 0001password --keypairgen --id 100 --key-type EC:secp384r1 pkcs11-tool --module $MODULE --login --pin 0001password --keypairgen --id 2 --key-type EC:prime256v1 pkcs11-tool --module $MODULE --login --pin 0001password --keypairgen --id 4 --key-type rsa:2048 --usage-sign pkcs11-tool --module $MODULE --login --pin 0001password --keypairgen --id 5 --key-type rsa:3072 --usage-sign echo "******************* Signing Tests ********************* " echo "this is test data" > data.txt pkcs11-tool --module $MODULE --sign --pin 0001password --id 100 -m ECDSA-SHA1 --signature-format openssl -i data.txt -o data.sig pkcs11-tool --module $MODULE --sign --pin 0001password --id 2 -m ECDSA-SHA1 --signature-format openssl -i data.txt -o data.sig pkcs11-tool --module $MODULE --sign --pin 0001password --id 4 -m SHA512-RSA-PKCS -i data.txt -o data.sig pkcs11-tool --module $MODULE --sign --pin 0001password --id 5 -m SHA512-RSA-PKCS -i data.txt -o data.sig rm data.txt rm data.sig echo "******************* Testing RSA Tests ********************* " pkcs11-tool --module $MODULE --login --pin 0001password --test #echo "******************* Testing EC Tests ********************* " #pkcs11-tool --module $MODULE --login --login-type so --so-pin 0001password --test-ec --id 200 --key-type EC:secp256r1 set +eyubihsm-shell-2.6.0/resources/tests/bash/test_eckey.sh0000755000175100001770000014546714666527773022510 0ustar runnerdocker#!/bin/bash set -u if [ "$#" -ne 1 ]; then BIN="yubihsm-shell" else BIN=$1 # path to the yubico-piv-tool command line tool fi if [ -e yubihsm-shell_test_dir ]; then rm -rf yubihsm-shell_test_dir fi mkdir yubihsm-shell_test_dir; cd yubihsm-shell_test_dir echo test signing data > data.txt test () { set +e $1 > output.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat output.txt rm output.txt exit 1 else echo "$2 ... OK!" rm output.txt fi set -e } test_with_resp () { set +e $1 > resp.txt 2>&1 ret=$? if [ $ret -ne 0 ]; then echo $1 cat resp.txt rm resp.txt exit 1 else echo "$2 ... OK!" fi set -e } set -e echo "====================== EC keys ===================== " set +e cat /etc/os-release | grep 'CentOS Linux 7' ret=$? set -e if [ $ret -ne 0 ]; then echo "------------- ECP224" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l \"ecKey\" -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecp224" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $keyid -t asymmetric-key" " get-object-info" info=$($BIN -p password -a get-object-info -i $keyid -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: ecp224\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"ecKey\"'" " Object info contains correct label" test "echo $info | grep \"domains: 5:8:13\"" " Object info contains correct domains" test "echo $info | grep \"origin: generated\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: derive-ecdh:sign-attestation-certificate:sign-ecdsa\"" " Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out ecp224-gen.pubkey" " Get public key" echo "Import Key:" test "openssl ecparam -genkey -name secp224r1 -noout -out secp224r1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l "ecKeyImport" -d "2,6,7" -c "sign-ecdsa,sign-attestation-certificate" --in=secp224r1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key" " get-object-info" info=$($BIN -p password -a get-object-info -i $import_keyid -t asymmetric-key 2> /dev/null) test "echo $info | grep \"id: $import_keyid\"" " Object info contains correct ID" test "echo $info | grep \"type: asymmetric-key\"" " Object info contains correct type" test "echo $info | grep \"algorithm: ecp224\"" " Object info contains correct algorithm" test "echo $info | grep 'label: \"ecKeyImport\"'" " Object info contains correct label" test "echo $info | grep \"domains: 2:6:7\"" " Object info contains correct domains" test "echo $info | grep \"origin: imported\"" " Object info contains correct origin" test "echo $info | grep \"capabilities: sign-attestation-certificate:sign-ecdsa\"" " Object info contains correct capabilities" test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out ecp224-import.pubkey" " Get public key" echo "Signing:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp224sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp224-gen.pubkey -signature data.ecp224sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp224sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp224-gen.pubkey -signature data.ecp224sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp224sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp224-gen.pubkey -signature data.ecp224sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp224sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp224-gen.pubkey -signature data.ecp224sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp224sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp224-import.pubkey -signature data.ecp224sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp224sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp224-import.pubkey -signature data.ecp224sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp224sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp224-import.pubkey -signature data.ecp224sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp224sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp224-import.pubkey -signature data.ecp224sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate: keyid $keyid import_keyid $import_keyid" set +e $BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 2>&1 > /dev/null # Some YubiHSMs does not have default attestation certificate def_attestation=$? set -e if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in secp224r1-keypair.pem -pubout -out secp224r1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in secp224r1-pubkey.pem --outformat binary --out secp224ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey secp224r1-keypair.pem -peerkey ecp224-gen.pubkey -out secp224ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp secp224ecdh-openssl.key secp224ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" fi echo "------------- ECP256" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecp256" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out ecp256-gen.pubkey" " Get public key" echo "Import key:" test "openssl ecparam -genkey -name secp256r1 -noout -out secp256r1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp256r1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out ecp256-import.pubkey" " Get public key" echo "Signing:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp256sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp256-gen.pubkey -signature data.ecp256sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp256sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp256-gen.pubkey -signature data.ecp256sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp256sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp256-gen.pubkey -signature data.ecp256sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp256sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp256-gen.pubkey -signature data.ecp256sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp256sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp256-import.pubkey -signature data.ecp256sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp256sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp256-import.pubkey -signature data.ecp256sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp256sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp256-import.pubkey -signature data.ecp256sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp256sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp256-import.pubkey -signature data.ecp256sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in secp256r1-keypair.pem -pubout -out secp256r1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in secp256r1-pubkey.pem --outformat binary --out secp256ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey secp256r1-keypair.pem -peerkey ecp256-gen.pubkey -out secp256ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp secp256ecdh-openssl.key secp256ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" echo "------------- ECP384" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecp384" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out ecp384-gen.pubkey" " Get public key" echo "Import key:" test "openssl ecparam -genkey -name secp384r1 -noout -out secp384r1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp384r1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out ecp384-import.pubkey" " Get public key" echo "Signing:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp384sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp384-gen.pubkey -signature data.ecp384sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp384sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp384-gen.pubkey -signature data.ecp384sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp384sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp384-gen.pubkey -signature data.ecp384sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp384sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp384-gen.pubkey -signature data.ecp384sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp384sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp384-import.pubkey -signature data.ecp384sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp384sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp384-import.pubkey -signature data.ecp384sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp384sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp384-import.pubkey -signature data.ecp384sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp384sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp384-import.pubkey -signature data.ecp384sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in secp384r1-keypair.pem -pubout -out secp384r1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in secp384r1-pubkey.pem --outformat binary --out secp384ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey secp384r1-keypair.pem -peerkey ecp384-gen.pubkey -out secp384ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp secp384ecdh-openssl.key secp384ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" echo "------------- ECP521" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecp521" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out ecp521-gen.pubkey" " Get public key" echo "Import key:" test "openssl ecparam -genkey -name secp521r1 -noout -out secp521r1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp521r1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out ecp521-import.pubkey" " Get public key" echo "Signing:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp521sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp521-gen.pubkey -signature data.ecp521sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp521sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp521-gen.pubkey -signature data.ecp521sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp521sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp521-gen.pubkey -signature data.ecp521sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp521sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp521-gen.pubkey -signature data.ecp521sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.ecp521sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify ecp521-import.pubkey -signature data.ecp521sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.ecp521sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify ecp521-import.pubkey -signature data.ecp521sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.ecp521sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify ecp521-import.pubkey -signature data.ecp521sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.ecp521sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify ecp521-import.pubkey -signature data.ecp521sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in secp521r1-keypair.pem -pubout -out secp521r1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in secp521r1-pubkey.pem --outformat binary --out secp521ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey secp521r1-keypair.pem -peerkey ecp521-gen.pubkey -out secp521ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp secp521ecdh-openssl.key secp521ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" echo "------------- ECK256" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A eck256" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out eck256-gen.pubkey" " Get public key" echo "Import key:" test "openssl ecparam -genkey -name secp256k1 -noout -out secp256k1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp256k1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out eck256-import.pubkey" " Get public key" echo "Signin:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.eck256sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify eck256-gen.pubkey -signature data.eck256sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.eck256sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify eck256-gen.pubkey -signature data.eck256sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.eck256sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify eck256-gen.pubkey -signature data.eck256sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.eck256sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify eck256-gen.pubkey -signature data.eck256sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.eck256sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify eck256-import.pubkey -signature data.eck256sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.eck256sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify eck256-import.pubkey -signature data.eck256sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.eck256sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify eck256-import.pubkey -signature data.eck256sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.eck256sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify eck256-import.pubkey -signature data.eck256sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in secp256k1-keypair.pem -pubout -out secp256k1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in secp256k1-pubkey.pem --outformat binary --out eck256ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey secp256k1-keypair.pem -peerkey eck256-gen.pubkey -out eck256ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp eck256ecdh-openssl.key eck256ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" set +e cat /etc/os-release | grep 'Fedora' is_fedora=$? cat /etc/os-release | grep 'CentOS Linux 7' is_centos7=$? set -e if [ $is_fedora -ne 0 ] && [ $is_centos7 -ne 0 ]; then echo "------------- Brainpool256" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecbp256" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out bp256-gen.pubkey" " Get public key" echo "Import key:" test "openssl ecparam -genkey -name brainpoolP256r1 -noout -out bp256r1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=bp256r1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out bp256-import.pubkey" " Get public key" echo "Signing:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.bp256sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify bp256-gen.pubkey -signature data.bp256sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.bp256sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify bp256-gen.pubkey -signature data.bp256sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.bp256sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify bp256-gen.pubkey -signature data.bp256sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.bp256sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify bp256-gen.pubkey -signature data.bp256sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.bp256sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify bp256-import.pubkey -signature data.bp256sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.bp256sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify bp256-import.pubkey -signature data.bp256sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.bp256sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify bp256-import.pubkey -signature data.bp256sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.bp256sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify bp256-import.pubkey -signature data.bp256sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in bp256r1-keypair.pem -pubout -out bp256r1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in bp256r1-pubkey.pem --outformat binary --out bp256ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey bp256r1-keypair.pem -peerkey bp256-gen.pubkey -out bp256ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp bp256ecdh-openssl.key bp256ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" echo "------------- Brainpool384" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecbp384" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out bp384-gen.pubkey" " Get public key" echo "Import key:" test "openssl ecparam -genkey -name brainpoolP384r1 -noout -out bp384r1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l ecKeyImport -d 1,2,3,4,5 -c sign-ecdsa,sign-attestation-certificate --in=bp384r1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out bp384-import.pubkey" " Get public key" echo "Signing:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.bp384sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify bp384-gen.pubkey -signature data.bp384sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.bp384sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify bp384-gen.pubkey -signature data.bp384sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.bp384sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify bp384-gen.pubkey -signature data.bp384sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.bp384sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify bp384-gen.pubkey -signature data.bp384sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.bp384sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify bp384-import.pubkey -signature data.bp384sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.bp384sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify bp384-import.pubkey -signature data.bp384sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.bp384sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify bp384-import.pubkey -signature data.bp384sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.bp384sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify bp384-import.pubkey -signature data.bp384sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der" " Sign attestation cert with imported key" test "rm selfsigned_cert.der" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in bp384r1-keypair.pem -pubout -out bp384r1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in bp384r1-pubkey.pem --outformat binary --out bp384ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey bp384r1-keypair.pem -peerkey bp384-gen.pubkey -out bp384ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp bp384ecdh-openssl.key bp384ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" echo "------------- Brainpool512" echo "Generate key:" test_with_resp "$BIN -p password -a generate-asymmetric-key -i 0 -l ecKey -d 5,8,13 -c sign-ecdsa,derive-ecdh,sign-attestation-certificate -A ecbp512" " Generate key" keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $keyid --outformat=PEM --out bp512-gen.pubkey" " Get public key" echo "Import key:" test "openssl ecparam -genkey -name brainpoolP512r1 -noout -out bp512r1-keypair.pem" " Generate key with OpenSSL" test_with_resp "$BIN -p password -a put-asymmetric-key -i 0 -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=bp512r1-keypair.pem" " Import key" import_keyid=$(tail -1 resp.txt | awk '{print $4}') test "$BIN -p password -a get-public-key -i $import_keyid --outformat=PEM --out bp512-import.pubkey" " Get public key" echo "Signing:" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.bp512sha1gen.sig" " Sign with generated key and ecdsa-sha1" test "openssl dgst -sha1 -verify bp512-gen.pubkey -signature data.bp512sha1gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.bp512sha256gen.sig" " Sign with generated key and ecdsa-sha256" test "openssl dgst -sha256 -verify bp512-gen.pubkey -signature data.bp512sha256gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.bp512sha384gen.sig" " Sign with generated key and ecdsa-sha384" test "openssl dgst -sha384 -verify bp512-gen.pubkey -signature data.bp512sha384gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.bp512sha512gen.sig" " Sign with generated key and ecdsa-sha512" test "openssl dgst -sha512 -verify bp512-gen.pubkey -signature data.bp512sha512gen.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt --outformat=PEM --out data.bp512sha1import.sig" " Sign with imported key and ecdsa-sha1" test "openssl dgst -sha1 -verify bp512-import.pubkey -signature data.bp512sha1import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt --outformat=PEM --out data.bp512sha256import.sig" " Sign with imported key and ecdsa-sha256" test "openssl dgst -sha256 -verify bp512-import.pubkey -signature data.bp512sha256import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt --outformat=PEM --out data.bp512sha384import.sig" " Sign with imported key and ecdsa-sha384" test "openssl dgst -sha384 -verify bp512-import.pubkey -signature data.bp512sha384import.sig data.txt" " Verify signature with OpenSSL" test "$BIN -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt --outformat=PEM --out data.bp512sha512import.sig" " Sign with imported key and ecdsa-sha512" test "openssl dgst -sha512 -verify bp512-import.pubkey -signature data.bp512sha512import.sig data.txt" " Verify signature with OpenSSL" echo "Get attestation certificate and a selfsigned certificate:" if [ $def_attestation -eq 0 ]; then test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem" " Sign attestation cert with default key" test "openssl x509 -in cert.pem -out cert.der -outform DER" " Convert cert format" test "$BIN -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der" " Import attestation cert as template cert (same ID as imported key)" test "rm cert.der" " Cleaning up" else test "$BIN -p password -a put-opaque -i $keyid -l template_cert_gen -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as generated key)" test "$BIN -p password -a put-opaque -i $import_keyid -l template_cert_imp -A opaque-x509-certificate --informat=PEM --in ../test_x509template.pem" " Import attestation cert as template cert (same ID as imported key)" fi test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem" " Sign attestation with same key (aka. get selfsigned cert)" test "$BIN -p password -a delete-object -i $keyid -t opaque" " Delete template cert" test "$BIN -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --informat=PEM --in selfsigned_cert.pem" " Import selfsigned cert with same key ID" test "rm selfsigned_cert.pem" " Cleaning up" #-- Sign attestation certificate test "$BIN -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.pem" " Sign attestation cert with imported key" test "rm selfsigned_cert.pem" " Cleaning up" echo "Derive ECDH:" test "openssl ec -in bp512r1-keypair.pem -pubout -out bp512r1-pubkey.pem" " Get imported key public key with OpenSSL" test "$BIN -p password -a derive-ecdh -i $keyid --in bp512r1-pubkey.pem --outformat binary --out bp512ecdh-shell.key" " Derive ECDH using yubihsm-shell" test "openssl pkeyutl -derive -inkey bp512r1-keypair.pem -peerkey bp512-gen.pubkey -out bp512ecdh-openssl.key" " Derive ECDH using OpenSSL" test "cmp bp512ecdh-openssl.key bp512ecdh-shell.key" " Compare ECDH value from yubihsm-shell and OpenSSL" echo "Clean up:" test "$BIN -p password -a delete-object -i $keyid -t asymmetric-key" " Delete generated key" test "$BIN -p password -a delete-object -i $import_keyid -t asymmetric-key" " Delete imported key" fi cd .. rm -rf yubihsm-shell_test_dir set +e yubihsm-shell-2.6.0/resources/tests/ps1/0000755000175100001770000000000014666527773017557 5ustar runnerdockeryubihsm-shell-2.6.0/resources/tests/ps1/test_hmackey.ps10000644000175100001770000001050614666527773022666 0ustar runnerdocker$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 echo "---------------------- HAMC keys --------------------- " echo "**********************************" echo " hmac-sha1" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha1"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: hmac-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha1"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "hmackey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: sign-hmac"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? echo "**********************************" echo " hmac-sha256" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha256"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? echo "**********************************" echo " hmac-sha384" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha384"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha384"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? echo "**********************************" echo " hmac-sha512" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-hmac-key -i $keyid -l "hmackey" -d "1,2,3" -c "sign-hmac" -A "hmac-sha512"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t hmac-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: hmac-sha512"; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t hmac-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.6.0/resources/tests/ps1/cmdline_test.ps10000644000175100001770000001021314666527773022653 0ustar runnerdocker$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different com mands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } yubihsm-shell.exe --version; CheckExitStatus -ECode $? yubihsm-shell.exe --help; CheckExitStatus -ECode $? yubihsm-shell.exe -a get-device-info; CheckExitStatus -ECode $? echo "********************** Reset YubiHSM ********************* " yubihsm-shell.exe -p password -a reset; CheckExitStatus -ECode $? Start-Sleep -s 10 echo "********************** Blink ********************* " yubihsm-shell.exe -p password -a blink; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a blink --duration=5; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a blink-device; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a blink-device --duration=5; CheckExitStatus -ECode $? echo "********************** Get Pseudo-random ********************* " yubihsm-shell.exe -p password -a get-pseudo-random; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-pseudo-random --count=10; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-pseudo-random --count=10 --out=random.txt; CheckExitStatus -ECode $? rm random.txt echo "********************** Asym keys ********************* " & "$PSScriptRoot\test_edkey.ps1" "$ARCH" & "$PSScriptRoot\test_eckey.ps1" "$ARCH" & "$PSScriptRoot\test_rsakey.ps1" "$ARCH" echo "********************** HMAC keys ********************* " & "$PSScriptRoot\test_hmackey.ps1" "$ARCH" echo "********************** AEAD keys ********************* " & "$PSScriptRoot\test_otpaeadkey.ps1" "$ARCH" Set-PSDebug -Trace 1 #echo "********************** Template ********************* " #echo "=== Import template" #$id=100 #yubihsm-shell.exe -p password -a get-pseudo-random --count=512 --out=template.txt; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a put-template -i $id -l template -d 1 -A template-ssh --in template.txt; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a get-object-info -i $id -t template; CheckExitStatus -ECode $? #echo "=== Get template" #yubihsm-shell.exe -p password -a get-template -i $id; CheckExitStatus -ECode $? #echo "=== Delete template" #yubihsm-shell.exe -p password -a delete-object -i $id -t template; CheckExitStatus -ECode $? #rm template.txt #echo "********************** Wrap keys ********************* " echo "********************** Authentication keys ********************* " echo "=== Create new authentication key" $id=200 yubihsm-shell.exe -p password -a put-authentication-key -i $id -l authkey -d 1,2,3 -c all --new-password foo123; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $id -t authentication-key; CheckExitStatus -ECode $? echo "=== Login using new authetication key" yubihsm-shell.exe --authkey $id -p foo123 -a get-object-info -i 1 -t authentication-key; CheckExitStatus -ECode $? echo "=== Delete new authentication key" yubihsm-shell.exe -p password -a delete-object -i $id -t authentication-key; CheckExitStatus -ECode $? Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.6.0/resources/tests/ps1/test_edkey.ps10000644000175100001770000000435014666527773022346 0ustar runnerdocker$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } echo "---------------------- ED keys --------------------- " # Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i 100 -l "edKey" -d "1,2,3" -c "sign-eddsa" -A "ed25519"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i 100 -t asymmetric-key; CheckExitStatus -ECode $? # Get public key yubihsm-shell.exe -p password -a get-public-key -i 100 > edkey1.pub; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i 100 --out edkey2.pub; CheckExitStatus -ECode $? # Signing yubihsm-shell.exe -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt > data.ed1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-eddsa -i 100 -A ed25519 --in data.txt --out data.ed2.sig; CheckExitStatus -ECode $? # Delete yubihsm-shell.exe -p password -a delete-object -i 100 -t asymmetric-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.6.0/resources/tests/ps1/test_eckey.ps10000644000175100001770000010004614666527773022344 0ustar runnerdocker$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin;C:/Users/dev/vcpkg/vcpkg-master/packages/openssl-windows_x86-windows/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin;C:/Users/dev/vcpkg/vcpkg-master/packages/openssl-windows_x64-windows/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } $env:Path += ";C:\Users\dev\vcpkg\vcpkg-master\packages\openssl-windows_x64-windows\tools\openssl" echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 $import_keyid=200 echo "---------------------- EC keys --------------------- " # ECP224 echo "**********************************" echo " ECP224" echo "**********************************" #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp224"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: asymmetric-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: ec224df"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "ecKey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 5:8:13"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: derive-ecdh:sign-attestation-certificate:sign-ecdsa"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp224r1 -noout -out secp224r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "2,6,7" -c "sign-ecdsa,sign-attestation-certificate" --in=secp224r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? # -- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp224sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp224sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp224sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp224sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp224sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp224sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp224sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp224sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp224r1-keypair.pem -pubout -out secp224r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp224r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECP256" echo "**********************************" # ECP256 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp256r1 -noout -out secp256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp256sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp256sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp256r1-keypair.pem -pubout -out secp256r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp256r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECP384" echo "**********************************" # ECP384 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp384"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp384r1 -noout -out secp384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp384sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp384sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp384r1-keypair.pem -pubout -out secp384r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp384r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECP512" echo "**********************************" # ECP512 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecp521"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl ecparam -genkey -name secp521r1 -noout -out secp521r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp521r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecp521sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecp521sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecp521sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecp521sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecp521sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecp521sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecp521sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecp521sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp521r1-keypair.pem -pubout -out secp521r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp521r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " ECK256" echo "**********************************" # ECK256 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "eck256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name secp256k1 -noout -out secp256k1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=secp256k1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.eck256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.eck256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.eck256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.eck256sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.eck256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.eck256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.eck256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.eck256sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in secp256k1-keypair.pem -pubout -out secp256k1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in secp256k1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " Brainpool256" echo "**********************************" # Brainpool256 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecbp256"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name brainpoolP256r1 -noout -out brainpool256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=brainpool256r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecbp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecbp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecbp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecbp256sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecbp256sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecbp256sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecbp256sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecbp256sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in brainpool256r1-keypair.pem -pubout -out brainpool256r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in brainpool256r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " Brainpool384" echo "**********************************" # Brainpool384 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecbp384"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name brainpoolP384r1 -noout -out brainpool384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=brainpool384r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecbp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecbp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecbp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecbp384sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecbp384sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecbp384sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecbp384sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecbp384sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in brainpool384r1-keypair.pem -pubout -out brainpool384r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in brainpool384r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? echo "**********************************" echo " Brainpool512" echo "**********************************" # Brainpool512 #-- Generate yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "ecKey" -d "5,8,13" -c "sign-ecdsa,derive-ecdh,sign-attestation-certificate" -A "ecbp512"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Import openssl.exe ecparam -genkey -name brainpoolP512r1 -noout -out brainpool512r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "ecKeyImport" -d "1,2,3,4,5" -c "sign-ecdsa,sign-attestation-certificate" --in=brainpool512r1-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM; CheckExitStatus -ECode $? #-- Sign yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha1 --in data.txt > data.ecbp512sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha256 --in data.txt > data.ecbp512sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha384 --in data.txt > data.ecbp512sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $keyid -A ecdsa-sha512 --in data.txt > data.ecbp512sha512.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha1 --in data.txt > data.ecbp512sha1.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha256 --in data.txt > data.ecbp512sha256.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha384 --in data.txt > data.ecbp512sha384.sig; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-ecdsa -i $import_keyid -A ecdsa-sha512 --in data.txt > data.ecbp512sha512.sig; CheckExitStatus -ECode $? #-- Get attestation certificate and a selfsigned certificate yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? rm selfsigned_cert.pem #-- Sign attestation certificate yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? #-- Derive ECDH openssl.exe ec -in brainpool512r1-keypair.pem -pubout -out brainpool512r1-pubkey.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a derive-ecdh -i $keyid --in brainpool512r1-pubkey.pem; CheckExitStatus -ECode $? #-- Delete yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.6.0/resources/tests/ps1/opensc_test.ps10000644000175100001770000000427714666527773022544 0ustar runnerdocker# This script runs on Powershell. If running tests on the current Powershell terminal is not permitted, run the # following command to allow it only on the current terminal: # >> Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process if($args.length -eq 0) { echo "Usage: ./opensc_tests.ps1 " echo "" echo "This script expects that libyubihsm.dll and the libcrypto.dll are on PATH and YUBIHSM_PKCS11_CONF environment variable is defined" exit } if ((Get-Command "pkcs11-tool.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path +=";C:\Program Files\OpenSC Project\OpenSC\tools" } $MODULE=$args[0] #$YHPKCS11CFG=$args[2] #$env:YUBIHSM_PKCS11_CONF=$YHPKCS11CFG Set-PSDebug -Trace 1 echo "******************* Generation Tests ********************* " pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 100 --key-type EC:secp384r1 pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 2 --key-type EC:prime256v1 pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 4 --key-type rsa:2048 pkcs11-tool.exe --module $MODULE --login --pin 0001password --keypairgen --id 5 --key-type rsa:3072 #Set-PSDebug -Trace 0 #exit echo "******************* Signing Tests ********************* " echo "this is test data" > Z:/data.txt pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 100 -m ECDSA-SHA1 --signature-format openssl -i Z:/data.txt -o Z:/data.sig pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 2 -m ECDSA-SHA1 --signature-format openssl -i Z:/data.txt -o Z:/data.sig pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 4 -m SHA512-RSA-PKCS -i Z:/data.txt -o Z:/data.sig pkcs11-tool.exe --module $MODULE --sign --pin 0001password --id 5 -m SHA512-RSA-PKCS -i Z:/data.txt -o Z:/data.sig rm Z:/data.txt rm Z:/data.sig echo "******************* Testing RSA Tests ********************* " pkcs11-tool.exe --module $MODULE --login --pin 0001password --test #echo "******************* Testing EC Tests ********************* " #pkcs11-tool.exe --module $MODULE --login --login-type so --so-pin 0001password --test-ec --id 200 --key-type EC:secp256r1 Set-PSDebug -Trace 0yubihsm-shell-2.6.0/resources/tests/ps1/test_otpaeadkey.ps10000644000175100001770000001242414666527773023374 0ustar runnerdocker$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 echo "---------------------- HAMC keys --------------------- " echo "**********************************" echo " AEAD Key 128" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-otp-aead-key -i $keyid -l "aeadkey" -d "1,2,3" -c "randomize-otp-aead" -A "aes128-yubico-otp" --nonce 0x01020304; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t otp-aead-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: otp-aead-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: aes128-yubico-otp"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "aeadkey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: randomize-otp-aead"; CheckExitStatus -ECode $? echo "=== Randomize OTP AEAD" yubihsm-shell.exe -p password -a randomize-otp-aead -i $keyid; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t otp-aead-key; CheckExitStatus -ECode $? echo "**********************************" echo " AEAD Key 192" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-otp-aead-key -i $keyid -l "aeadkey" -d "1,2,3" -c "randomize-otp-aead" -A "aes192-yubico-otp" --nonce 0x01020304; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t otp-aead-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: otp-aead-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: aes192-yubico-otp"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "aeadkey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: randomize-otp-aead"; CheckExitStatus -ECode $? echo "=== Randomize OTP AEAD" yubihsm-shell.exe -p password -a randomize-otp-aead -i $keyid; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t otp-aead-key; CheckExitStatus -ECode $? echo "**********************************" echo " AEAD Key 256" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-otp-aead-key -i $keyid -l "aeadkey" -d "1,2,3" -c "randomize-otp-aead" -A "aes256-yubico-otp" --nonce 0x01020304; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t otp-aead-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: otp-aead-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: aes256-yubico-otp"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "aeadkey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1:2:3"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: randomize-otp-aead"; CheckExitStatus -ECode $? echo "=== Randomize OTP AEAD" yubihsm-shell.exe -p password -a randomize-otp-aead -i $keyid; CheckExitStatus -ECode $? echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t otp-aead-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.6.0/resources/tests/ps1/test_rsakey.ps10000644000175100001770000005311414666527773022545 0ustar runnerdocker$ARCH=$args[0] if($ARCH -eq "x86") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files (x86)/Yubico/YubiHSM Shell/bin" } } elseif ($ARCH -eq "x64") { if ((Get-Command "yubihsm-shell.exe" -ErrorAction SilentlyContinue) -eq $null) { $env:Path += ";C:/Program Files/Yubico/YubiHSM Shell/bin" } } else { echo "Usage: ./cmdline_test.ps1 " echo "" echo "This is a test script that uses the yubihsm-shell command line tool to reset the conncted YubiHSM and then different commands." echo "" echo " x86 expects that yubihsm-shell.exe is installed in 'C:/Program Files (x86)/Yubico/Yubico PIV Tool/bin'" echo " x64 expects that yubhsm-shell.exe is installed in 'C:/Program Files/Yubico/Yubico PIV Tool/bin'" exit } echo "Running commands on $ARCH architecture" $TEST_DIR = "yubihsm-shell_test_dir" Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue New-Item $TEST_DIR -type Directory -Force cd $TEST_DIR echo "test signing data" > data.txt Set-PSDebug -Trace 1 $ErrorActionPreference = "Stop" function CheckExitStatus { param ( $ECode ) if(!$ECode) { echo "Fail!" exit } } $keyid=100 $import_keyid=200 echo "---------------------- RSA keys --------------------- " echo "**********************************" echo " RSA2048" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "rsaKey" -d "1" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" -A "rsa2048"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x0064"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: asymmetric-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: rsa2048"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "rsaKey"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 1"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: generated"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss"; CheckExitStatus -ECode $? rm info.txt echo "=== Get public key of generated key" yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey.pem; CheckExitStatus -ECode $? echo "=== Import into YubiHSM" openssl.exe genrsa -out rsa2048-keypair.pem 2048; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "rsaKeyImport" -d "2" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" --in=rsa2048-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key > info.txt; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "id: 0x00c8"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "type: asymmetric-key"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "algorithm: rsa2048"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern 'label: "rsaKeyImport"'; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "domains: 2"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "origin: imported"; CheckExitStatus -ECode $? Select-String -Path "info.txt" -Pattern "capabilities: decrypt-oaep:decrypt-pkcs:sign-attestation-certificate:sign-pkcs:sign-pss"; CheckExitStatus -ECode $? echo "=== Get public key of imported key" yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_imported.pem; CheckExitStatus -ECode $? echo "=== Signing with generated key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --out data.2048pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --out data.2048pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --out data.2048pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --out data.2048pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.2048psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.2048psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.2048psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.2048psssha512.sig; CheckExitStatus -ECode $? echo "=== Signing with imported key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --out data.2048pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --out data.2048pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --out data.2048pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --out data.2048pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.2048psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.2048psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.2048psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.2048psssha512.sig; CheckExitStatus -ECode $? echo "=== Make self signed certificate" yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? echo "=== Sign attestation certificate" yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? echo "=== Decrypt with generated key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey.pem -pubin -in data.txt -out data.enc; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec; CheckExitStatus -ECode $? if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Decrypt with imported key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey_imported.pem -pubin -in data.txt -out data.enc; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec; CheckExitStatus -ECode $? if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "**********************************" echo " RSA3072" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "rsaKey" -d "1" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" -A "rsa3072"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of generated key" yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey.pem; CheckExitStatus -ECode $? echo "=== Import into YubiHSM" openssl.exe genrsa -out rsa3072-keypair.pem 3072; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "rsaKeyImport" -d "2" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" --in=rsa3072-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of imported key" yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_imported.pem; CheckExitStatus -ECode $? echo "=== Signing with generated key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --out data.3072pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --out data.3072pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --out data.3072pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --out data.3072pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.3072psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.3072psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.3072psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.3072psssha512.sig; CheckExitStatus -ECode $? echo "=== Signing with imported key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --out data.3072pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --out data.3072pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --out data.3072pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --out data.3072pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.3072psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.3072psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.3072psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.3072psssha512.sig; CheckExitStatus -ECode $? echo "=== Make self signed certificate" yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? echo "=== Sign attestation certificate" yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? <# echo "=== Decrypt with generated key and PKCS1v15" openssl rsautl -encrypt -inkey pubkey.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Decrypt with imported key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey_imported.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec <# if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec #> echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? # RSA 4096 echo "**********************************" echo " RSA4096" echo "**********************************" echo "=== Generate on YubiHSM" yubihsm-shell.exe -p password -a generate-asymmetric-key -i $keyid -l "rsaKey" -d "1" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" -A "rsa4096"; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of generated key" yubihsm-shell.exe -p password -a get-public-key -i $keyid --outformat=PEM --out pubkey.pem; CheckExitStatus -ECode $? echo "=== Import into YubiHSM" openssl.exe genrsa -out rsa4096-keypair.pem 4096; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-asymmetric-key -i $import_keyid -l "rsaKeyImport" -d "2" -c "sign-pkcs,sign-pss,decrypt-pkcs,decrypt-oaep,sign-attestation-certificate" --in=rsa4096-keypair.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a get-object-info -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? echo "=== Get public key of imported key" yubihsm-shell.exe -p password -a get-public-key -i $import_keyid --outformat=PEM --out pubkey_imported.pem; CheckExitStatus -ECode $? echo "=== Signing with generated key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha1 --in data.txt --out data.4096pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha256 --in data.txt --out data.4096pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha384 --in data.txt --out data.4096pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $keyid -A rsa-pkcs1-sha512 --in data.txt --out data.4096pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha1 --in data.txt --out data.4096psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha256 --in data.txt --out data.4096psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha384 --in data.txt --out data.4096psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $keyid -A rsa-pss-sha512 --in data.txt --out data.4096psssha512.sig; CheckExitStatus -ECode $? echo "=== Signing with imported key and" echo "===== rsa-pkcs1-sha1" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha1 --in data.txt --out data.4096pkcs1sha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha256" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha256 --in data.txt --out data.4096pkcs1sha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha384" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha384 --in data.txt --out data.4096pkcs1sha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pkcs1-sha512" yubihsm-shell.exe -p password -a sign-pkcs1v15 -i $import_keyid -A rsa-pkcs1-sha512 --in data.txt --out data.4096pkcs1sha512.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha1" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha1 --in data.txt --out data.4096psssha1.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha256" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha256 --in data.txt --out data.4096psssha256.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha384" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha384 --in data.txt --out data.4096psssha384.sig; CheckExitStatus -ECode $? echo "===== rsa-pss-sha512" yubihsm-shell.exe -p password -a sign-pss -i $import_keyid -A rsa-pss-sha512 --in data.txt --out data.4096psssha512.sig; CheckExitStatus -ECode $? echo "=== Make self signed certificate" #yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id 0 --out cert.pem; CheckExitStatus -ECode $? openssl.exe x509 -in cert.pem -out cert.der -outform DER; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$keyid --out selfsigned_cert.pem; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $keyid -t opaque; CheckExitStatus -ECode $? #yubihsm-shell.exe -p password -a put-opaque -i $keyid -l java_cert -A opaque-x509-certificate --in selfsigned_cert.pem; CheckExitStatus -ECode $? echo "=== Sign attestation certificate" yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t opaque; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a put-opaque -i $import_keyid -l template_cert -A opaque-x509-certificate --in cert.der; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a sign-attestation-certificate -i $keyid --attestation-id=$import_keyid --out selfsigned_cert.der; CheckExitStatus -ECode $? <# echo "=== Decrypt with generated key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $keyid --in data.enc --out data.dec if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec echo "=== Decrypt with imported key and PKCS1v15" openssl.exe rsautl -encrypt -inkey pubkey_imported.pem -pubin -in data.txt -out data.enc yubihsm-shell.exe -p password -a decrypt-pkcs1v15 -i $import_keyid --in data.enc --out data.dec if (@(Compare-Object $(Get-Content "data.txt") $(Get-Content "data.dec") -sync 0).length -ne 0) { echo "Decrypt failed" exit 2 } rm data.dec #> echo "=== Delete keys" yubihsm-shell.exe -p password -a delete-object -i $keyid -t asymmetric-key; CheckExitStatus -ECode $? yubihsm-shell.exe -p password -a delete-object -i $import_keyid -t asymmetric-key; CheckExitStatus -ECode $? cd .. Remove-Item -Path "$TEST_DIR" -Recurse -ErrorAction SilentlyContinue Set-PSDebug -Trace 0yubihsm-shell-2.6.0/resources/make_src_dist.sh0000755000175100001770000000130214666527773021054 0ustar runnerdocker#!/bin/bash # Script to produce the source distribution package VERSION=$1 # Full yubihsm-shell version, tex 2.1.0 mkdir dist_build; cd dist_build cmake .. make cd .. rm -r dist_build set +e set -x tar --exclude README \ --exclude .git \ --exclude .github \ --exclude .gitignore \ --exclude .ci \ --exclude .clang-format \ --exclude .pre-commit-config.yaml \ --exclude .travis.yml \ --transform="s/^\./yubihsm-shell-$VERSION/" -czf yubihsm-shell-$VERSION.tar.gz . exitcode=$? if [ "$exitcode" != "1" ] && [ "$exitcode" != "0" ]; then exit $exitcode fi set -eyubihsm-shell-2.6.0/resources/release/0000755000175100001770000000000014666527773017332 5ustar runnerdockeryubihsm-shell-2.6.0/resources/release/icons/0000755000175100001770000000000014666527773020445 5ustar runnerdockeryubihsm-shell-2.6.0/resources/release/icons/yubico-msi-background.png0000644000175100001770000001531314666527773025353 0ustar runnerdocker‰PNG  IHDRí8vG«gsRGB®ÎéDeXIfMM*‡i  í 8-lÖú5IDATxíÝis[×y𸈢hÙrÇÎæi:]^´NßôëôKõã´/:Óé$m§“IÒÉæÔ’µX{ÏE" )$Ààïf8îòÜßãñ?¸¸KíŸÿýGÉD ˆÀ?ýý¿©Dˆ'PW’Š @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ í€MQ( í’Š1 P@hlŠ’ @€@I@h—TŒ @€€B;`S”D€JB»¤bŒÚ›¢$ PÚ%c @  €ÐØ% @€’€Ð.©#@€„vÀ¦(‰”„vIÅ( ´6EI @ $ ´K*Æ @€@@¡°)J"@€%¡]R1F€ 4Ö¤¤% ´6öÒNóãÔjì§F­•êµ4 Ò`ÔI§ýWé¤÷mêô_.¹*›#@€w„ö»"7èýF½•>Þù³´½yðÞ^×S#ÿ¯•ƒüvÚßúÞ8¼¿=þeê ÛïÍk€–#àðørœÃm¥™¿]¶÷wÅÀ.»•Ãûþí¿M[;¥ @€À„ö£m¢^ÛL÷nýEª×g;ÐR6¯–kÔ·¢í’z p#„öhóôNÞÙú"okzð‚ïêµF:ØþÑç6\¥€Ð¾JÍXW-[Þk}÷ÌJÃ^êNÓ`ØMi4*η›OZóm»Hc ˜íøèBK±òeT¿I×jµ©Muú‡éÅéWé´÷"Ò`â³ZÚn¤;ÛßÏ'¤íMŒ§ñøa÷áÔ˜7 °Xß´ëní[ù´É©“/ézxøŸ©/ëšìj®Qj÷Ÿ?¯.ýšœª³ÊM °\¡½\ïkßZ½Þœªá°óM~_> þvÆQz~ò›·oó«z}sê½7 °x¡½xãP[¨N$›œ.zÝuox2¹Xª§©÷Þ @€Àâ„öâCma”ït695jÓß¼'?›|]݈erNýö=ù‰× °(¡½(Ù ëŒòYáÓnëÓ‰wg¿¼Ý¼?õá0Ÿen"@€å íåz_ûÖª3Å'§ÍÒ'»Õ S¶'‡ß¼®nÄr°õƒ´·5}™Xg0½ž7 xA€ ˜þsa›±â(§Õƒ?ªë¯'.ûª®»®þúƒN¾·øIþx²9¾Ëø&,ó¾Þêò0,W@h/×ûÚ·6õÒQ÷qºU8,ÞØh¥êïCS»÷|îšÏç pµ_­çJ¬íùéïÒpØŸ«ÖQþ–þ¬=}ù×\+²Ì, ´g&[ýÃNz|üó||8ÛÎäÀ~zü‹Ô϶œ¹  @àJ„ö•0®ÞJNû/҃ߥî`úúë³ö¤ºùÃÃÿJǽ'gÍbœ,à7íG^}õùÁ«ÿH;›wóßÇãgeoä;¦U÷&¯ƒW—‡U·9=É·8= @àz„öõú‡ØzÊÕßÛ©z È‡nmúvn¯ @`9/ÇyŶ"°W¬aÊ%@à†ø¦}C=¹›Õ³°o5¿39”ª›¥TOúzwjå§‚í6ïM wŸäù§Ÿú55ƒ7 °¡½ÖØ+ÝkÝOû[ŸOùôøWSï_¿¦aªæ¯ÕÞ”©n¸R}n"@€å ¼ý/ñr·kk×(Púæ|Ô­ÑùþT¬öôd:зó‰kï>-ìý% @€ÀU í« ¾¾f>Ü=¾5éë:«›¥œüúõ»â?«3Ç»ý·×fWg—o7Šó$@€Å íÅÙ†\ófþ={r:é=_Ú59Vzýî%_›»¥ÙŒ @€À„öq#®º: mrºèÝÍzÃöäbi£¾9õÞX¼€Ð^¼q¨-T7O™œ†i0ùöÌ×£w®Û®%ÿ꜉å,HÀyuµï†ïEs7ë;S»4Í÷À‘©•xC€3 홸VæêÑœ“SuBYõììM;Í»S³í)o °¡½æ8™< ¼ªªúmú“Ý?Ï×aoœYduMw«q{êó®'}MyxC€e¸¹Ê2”mc|'³|™WNé7Umo¤ÏoÿCzÙùÃøÒ®~>é¬úö½¹±=¾±Ê»]-X=HÄD€ËÚËõ¾ö­U‡µ«‡ƒì4?žª¥^o¤ƒíNõæ´÷âB—‰µ¼q˜OÀáñùÜVz©—§¸Tý/OÿïRË[˜æÚó¹­ôRÕÃA^~=×>T i÷ŸÍµ¬… @àrBûr~+»ô³ö¯ÓQ¾=é,S»÷<==þå,‹˜—®PÀoÚWˆ¹j«zzü‹tšƒø`ûGçÞá¬úüEû«ôªS};÷¬íUë³z X¡½>½œkOŽºÆß¸·û©:‹|£ÖLõ|XÔƒa7ö_Žƒ}”Ñi"@€ëÚ×ëdë£Î/ÆA Rü¦]@1D€" íˆ]Q(8<^@Y‡¡½æý©[“¶ó UªÇkÖÒFþíúÎ¥w±§F{BØ¥7f 0Úkú/Âþö©Qo½Ù»'ÇÝÔë¶óYâÍtïÖ_¾Ÿ÷ŃW?MÝÁѼ‹[Žæpx|4‹ @€ëÚסn› @`¡=šE @€ÀuíëP·M 0‡€Ñæ@[…Ež·›êùLñ×S§8~9vÒ7‡ÿýzxîöí¹—µ Ì' ´çs ¿Ôñ©nGZÝýÌD€«'àðøêõLÅ pC„ö m¼Ý&@€Õpx|õzvåo5î¤æÆ­ñÍXª²Ôk|ÊWx:~ÊWõíQr÷³+‡·BÌ( ´g[§Ùw›÷ÒþÖ9°wÎÜ­Ûé³ñc:_~^œ~•çó<í3±|@€ íG\}uÿñOó­L·.xòz­‘îl?ß³ü£ôèèrˆ÷"î–š °ö~Ó^û¿¿ƒww¾¼p`O.Ýjì¥ïÜúëñCG&ǽ&@€åíå8‡ÙJ£¾nµ>»žfãVþÖýÅÜË[æÚóÛ­ä’;›w/]÷íÖ÷|Û¾´¢ @`v¿iÏn¶ÒKlÖ·Þ«4¦ÃÎÃtÜ}’ú£NûùLòfjäÔöZ÷ÓNþ-{rªÕjãgrŸägt› @`yB{yÖ1¶”÷ÝéñÑÏS»ÿlj¸7l§ê¯ƒùvë³ôÑΧ>¯³› @`¹/×ûÚ·6v§jèöÞ ì©ò›W¯S5ßäTËÈM °\¡½\ïkßZu£”É©;<™|{æëÓþ˩Ϫ¯˜ @`¹B{¹Þ×¾µÎàUêÞõF¾ûÙE¦~~:ØäÔÚ“^ @`)B{)̱6òüä×o jmìå×>Ô]Ý`åõT=–³;øã£>_ù',^à퉿-[X¢ÀæÆnŽâòÿ'Œúù³çù ðƒT¯7ÆgˆŸ¾sØüÝR·ûo†NòYæ&X¾€Ð^¾ùR¶øé­¿?ä"«î6Ë´Ÿo®rØ}”úùìr,O üUlyÛ·% @à‚Bû‚Pf#@€×- ´¯»¶O€.( ´/e6 pÝND»î,hûÏòe]õÚÆ‚ÖžÒ`4}gµ…mÈŠ  @à€Ð~C±^/NzO×k‡ì œq!/ @ œ€ß´ÃµDA @ , ´Ë.F  @€@8¿i‡kÉ¢ ª¥[Í{—ÞÈI~Îö0ßÕD€ËÚ˳±¥Z­ž>ÞýÉ¥kyðê§ù¡!ÓÏØ¾ôJ­€Îpxü\ @€8B;N/TB€ÎÚçòøÄÚqz¡ p®€ÑÎåY¿G£Azðêg3íØ­/ÒNóîx™£îãô²ýûü,íÎLë03\^@h_ÞpåÖÐÎTó‹Ó¯Þ„vu¹Øáé×i”Ú3­ÃÌ py‡Ç/o¸ök¨B~òšìv¾\û}¶ƒˆ( ´#v%`MýÁ雪Z½Ôjì¿yï,G@h/Çyå·²QoNíÃNã`ê½7 °x¡½xã•ßÂþÖçéÝÐÞ¨·V~¿ìVMÀ‰h«Ö±KÖ[«m¤ƒ­|p-µTKõúf> ~;5 =ʧ¢™ @`¹B{¹Þ×¾µzÚH··>»t½ÁÉ¥×a 0›€Ãã³y™ûO/G€—Ú—7¼qk8î>MþË·ßv˜×- ´¯»+¶ýÓÞËôíÉÿ®XÕÊ%@€ÀzøM{=ú¸°½F©7l§þ ŽºÒIïé¶eÅ p¾€Ð>ßgí>ŒºéwÏÿeíöË @à&8<~ºl  @`-„öZ´ÑN @€ÀMÚ7¡Ëûبo§û{“n5?­nŸ2ñ‰— ]ÀoÚÑ;´€úþøÀŸ¤v~œŽ:Òaça>ÙÌÍR@m•¸R¡}¥œ«µ²z­1¾;Zu‡´êR®ÃîÃtÜ}’wÂ-JW«“ª%@à¦í›ÒéìçÖæ~ªþîn™Ãû›üíûAêß>Žó‹û˜– ´—€¼J›¨×ië{ã¿vïùøÐùIïÛ¼ ¾}¯RÕJ€Àz íõìë™{5JÃ4 R=?íëCÓöæAªþÃnïüí;> ;ZÌç ° ¡½ ب«­B÷/þ-ílÞM»ÍOr(ßMµZíÜr«gißÙþbüwÒývüí»Ývî2>$@€«ÚWo~Õ·íãÞ“ñ_õ|íÝÍOò%`÷òoÚw>XûNónªþúƒNþæý`|öyu—5,^@h/Þ8ôFùPùQ>ñ¬úÛ¨5Çß¾ws€W—…756Zé`û‡é`ë9ü«oßÒiÿÅy‹øŒ.) ´/ ¸N‹Wߘ_u¾ÿU7a©®ãÞÙüèü]̇Öw›ÿzù¡"ÏÚ¿Iíñ‰kç/æS˜]@hÏn¶ÖKlÔ[㻥UwLÛÜØži_«ù·w„öLjf&@€ÀÅ„öÅ­ÖvÎZÊ¿kçoËUP_äwíµ…°c. ´ƒ7h‘åmåoÅUPWg‘×j3܇S¿—n·>KÍÆîEWk>˜C@hÏvéNÆ—qwç;¨õÏÜåêšï×—Œµûù²±Í3çõ\N@h_Îo­–ª~œ¿U?LÁáÌûÖ鿜y  @€ÀÅ„öÅ­ÖvÎNÿðO¿U?άí~Ú1¬º€Ð^õÎYuÈû¨óhüÎÞàxεXŒ–) ´—©`[UX?9þE:é>Íߪ‡*R\T@h_TjMæŽz©:¹ÌD€«'0Ã5VoçTL€ÖI@h¯S7í ¬µ€Ð^ëöÚ9X'¡½NÝ´/ °ÖB{­Ûkç @`„ö:uÓ¾ @€ÀZ íµn¯#@€uÚëÔMûB€k- ´×º½vŽÖI@h¯S7í ¬µ€Ð^ëöÚ9X'ÿþ÷€Æ(q:ÈIEND®B`‚yubihsm-shell-2.6.0/resources/release/icons/yubico-msi-y-banner.png0000644000175100001770000000512314666527773024745 0ustar runnerdocker‰PNG  IHDRí:øØsRGB®ÎéDeXIfMM*‡i  í :œðV? ½IDATxíÝýo[WÀñÇyqâÄIœÄ‰“lmÒ¦Mºví¶NBˆ­cc£ÚÚ‰QBBâ`“š@B!hÚËŸ€øa¼ˆ!Ö :Ø ›&~@ÛÚukº$uKÉÜÄyãØŽmÎ9é½±“8½Žm©¾ùžªõ=çžsêó±¥G÷úÜsóó7ºü±¬fâ[BÔÖ4H‡oPöµVtž”fopËz¥´KÑ£- €€k2ÙU¹<ùgy?òŠ,%#EÓWß)GC_•#¡3R§‚y¹A»\’ôƒ à¥ä¤¼~^þ;ÿŽ=&ÔJ°yXzüG¥Ý·OëâQVVd.–ÈÒ™Š]–Œºen¥ž–ûå‘ïI[㫨¤W‚vI|4Fp›À\üºœýÌ­„ÍÐöCYNMç {lúœÄÔóÙVò{{äî¶OYÙ¼W°ßÿ±LÅ>2åí¾ýrï7óê›ñ¨Yrë7æ‹mM}@\$ 7ÿÐ{_[YÚjoíPËZ0ÿ ò;™ŽÚ#îk}Pí}ÒÎ[QµÉÛáçe2ö¡)Ò«¡zA‚ÍCV•½´wÄF#@· L©äçF¿on=ÑìP÷äp×—%àÛþÖöBbBF¦þ"—&ÿ`O<ÓK£>>ø#ék=^2A»dB:@p›€^å|øg2¹ô=4=‰¬§å˜ôµ< ‚÷€™¸¦=Õ·Áõ¢,úoý,v2½d·éôûžS[uÛe¥´KÑ£- €€kRé¸\ˆ¼bK¤Š§~Žûžî/šß°êZŠj»]e‚öv:œCØõú–÷•èkž=/ú \ï‡](µ5ìQ[sžP{jŸRWãý…ªí¸œ ½c:"€ì&ÕLBí°L/ÊÅ›¿±7 Ñ›èµÄõ­p½²Z}­¯b,íŠÑÒ1 €åà9íòzÒ € hWŒ–Ž@(¯A»¼žô† €@ÅÚ£¥c@Ê+@Ð.¯'½!€ P1‚vÅhé@ò ´ËëIo €TL€ ]1Z:F@ ¼íòzÒ € hWŒ–Ž@(¯A»¼žô† €@ÅÚ£¥c@Ê+@Ð.¯'½!€ P1ÿï{[œIEND®B`‚yubihsm-shell-2.6.0/resources/release/linux/0000755000175100001770000000000014666527773020471 5ustar runnerdockeryubihsm-shell-2.6.0/resources/release/linux/build-all.sh0000755000175100001770000000063214666527773022676 0ustar runnerdocker#!/bin/bash set -e -o pipefail -x for machine in focal jammy kinetic debian10 debian11 fedora36 fedora37 centos7; do vagrant box update $machine time vagrant up $machine vagrant rsync-back $machine set +e vagrant destroy -f $machine set -e done for machine in trusty xenial bionic; do vagrant box update $machine time vagrant up $machine set +e vagrant destroy -f $machine set -e done yubihsm-shell-2.6.0/resources/release/linux/licenses/0000755000175100001770000000000014666527773022276 5ustar runnerdockeryubihsm-shell-2.6.0/resources/release/linux/licenses/libusb0000644000175100001770000006350414666527773023511 0ustar runnerdocker GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! yubihsm-shell-2.6.0/resources/release/linux/licenses/openssl0000644000175100001770000001376014666527773023713 0ustar runnerdocker LICENSE ISSUES ============== The OpenSSL toolkit stays under a double license, i.e. both the conditions of the OpenSSL License and the original SSLeay license apply to the toolkit. See below for the actual license texts. OpenSSL License --------------- /* ==================================================================== * Copyright (c) 1998-2017 The OpenSSL Project. 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. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" * * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please contact * openssl-core@openssl.org. * * 5. Products derived from this software may not be called "OpenSSL" * nor may "OpenSSL" appear in their names without prior written * permission of the OpenSSL Project. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by the OpenSSL Project * for use in the OpenSSL Toolkit (http://www.openssl.org/)" * * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY * EXPRESSED 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 OpenSSL PROJECT OR * ITS 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. * ==================================================================== * * This product includes cryptographic software written by Eric Young * (eay@cryptsoft.com). This product includes software written by Tim * Hudson (tjh@cryptsoft.com). * */ Original SSLeay License ----------------------- /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * * This package is an SSL implementation written * by Eric Young (eay@cryptsoft.com). * The implementation was written so as to conform with Netscapes SSL. * * This library is free for commercial and non-commercial use as long as * the following conditions are aheared to. The following conditions * apply to all code found in this distribution, be it the RC4, RSA, * lhash, DES, etc., code; not just the SSL code. The SSL documentation * included with this distribution is covered by the same copyright terms * except that the holder is Tim Hudson (tjh@cryptsoft.com). * * Copyright remains Eric Young's, and as such any Copyright notices in * the code are not to be removed. * If this package is used in a product, Eric Young should be given attribution * as the author of the parts of the library used. * This can be in the form of a textual message at program startup or * in documentation (online or textual) provided with the package. * * 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 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. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * "This product includes cryptographic software written by * Eric Young (eay@cryptsoft.com)" * The word 'cryptographic' can be left out if the rouines from the library * being used are not cryptographic related :-). * 4. If you include any Windows specific code (or a derivative thereof) from * the apps directory (application code) you must include an acknowledgement: * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" * * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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 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. * * The licence and distribution terms for any publically available version or * derivative of this code cannot be changed. i.e. this code cannot simply be * copied and put under another distribution licence * [including the GNU Public Licence.] */ yubihsm-shell-2.6.0/resources/release/linux/yubihsm-shell.spec0000644000175100001770000000514614666527773024140 0ustar runnerdocker%global _yubihsm yubihsm Name: yubihsm-shell Version: 2.6.0 Release: 1%{?dist} Summary: Tools to interact with YubiHSM 2 License: Apache 2.0 URL: https://github.com/Yubico/yubihsm-shell %description This package contains most of the components used to interact with the YubiHSM 2 at both a user-facing and programmatic level. It contains the libyubihsm, yubihsm-shell, yubihsm-pkcs11, yubihsm-wrap and yubihsm-auth %package -n %{_yubihsm}-devel Summary: Development tools for interacting with YubiHSM 2 %description -n %{_yubihsm}-devel Development libraries for working with yubihsm 2. %prep cd %{_builddir} rm -rf * cp -r $INPUT/* . %build rm -rf build mkdir build && cd build $CMAKE -DRELEASE_BUILD=1 -DWITHOUT_YKYH=1 -DWITHOUT_MANPAGES=1 -DYUBIHSM_INSTALL_LIB_DIR="%{buildroot}/%{_prefix}/lib64/" -DYUBIHSM_INSTALL_INC_DIR="%{buildroot}/%{_prefix}/include/" -DYUBIHSM_INSTALL_BIN_DIR="%{buildroot}/%{_prefix}/bin/" -DYUBIHSM_INSTALL_MAN_DIR="%{buildroot}/%{_prefix}/man/" -DYUBIHSM_INSTALL_PKGCONFIG_DIR="%{buildroot}/%{_prefix}/lib64/pkgconfig/" .. make #Would be nice to use %license, but that macro does not seem to work on Centos, so the license needs to be installed manually %install rm -rf %{buildroot} mkdir -p %{buildroot} cd build make install chrpath -r %{_libdir} %{buildroot}/%{_bindir}/yubihsm-shell chrpath -r %{_libdir} %{buildroot}/%{_bindir}/yubihsm-wrap chrpath -r %{_libdir} %{buildroot}/%{_bindir}/yubihsm-auth chrpath -r %{_libdir} %{buildroot}/%{_libdir}/libykhsmauth.so chrpath -r %{_libdir} %{buildroot}/%{_libdir}/pkcs11/yubihsm_pkcs11.so mkdir -p %{buildroot}/%{_prefix}/share/licenses/%{name} install -m 0644 ../LICENSE %{buildroot}/%{_prefix}/share/licenses/%{name} %files %{_prefix}/share/licenses/%{name}/LICENSE %{_bindir}/yubihsm-shell %{_bindir}/yubihsm-wrap %{_bindir}/yubihsm-auth %{_libdir}/libyubihsm.so.2 %{_libdir}/libyubihsm.so.2.* %{_libdir}/libyubihsm_http.so.2 %{_libdir}/libyubihsm_http.so.2.* %{_libdir}/libyubihsm_usb.so.2 %{_libdir}/libyubihsm_usb.so.2.* %{_libdir}/libykhsmauth.so.2 %{_libdir}/libykhsmauth.so.2.* %dir %{_libdir}/pkcs11 %{_libdir}/pkcs11/yubihsm_pkcs11.so %files -n %{_yubihsm}-devel %{_libdir}/libyubihsm.so %{_libdir}/libyubihsm_http.so %{_libdir}/libyubihsm_usb.so %{_libdir}/libykhsmauth.so %{_includedir}/yubihsm.h %{_includedir}/ykhsmauth.h %dir %{_includedir}/pkcs11 %{_includedir}/pkcs11/pkcs11.h %{_includedir}/pkcs11/pkcs11f.h %{_includedir}/pkcs11/pkcs11t.h %{_includedir}/pkcs11/pkcs11y.h %{_libdir}/pkgconfig/yubihsm.pc %{_libdir}/pkgconfig/ykhsmauth.pc %changelog * Wed Mar 27 2024 Aveen Ismail - 2.6.0 - Releasing version 2.6.0 yubihsm-shell-2.6.0/resources/release/linux/build-rpm.sh0000644000175100001770000000630414666527773022723 0ustar runnerdocker#!/usr/bin/env bash set -e -o pipefail set -x PLATFORM=$1 if [ "$PLATFORM" == "centos7" ]; then sudo yum -y install centos-release-scl sudo yum -y update && sudo yum -y upgrade sudo yum -y install devtoolset-7-gcc \ devtoolset-7-gcc-c++ \ devtoolset-7-make \ chrpath \ git \ cmake \ openssl-devel \ libedit-devel \ libcurl-devel \ libusbx-devel \ rpm-build \ redhat-rpm-config \ pcsc-lite-devel . /opt/rh/devtoolset-7/enable GENGETOPT_VER=2.23 curl -o gengetopt-${GENGETOPT_VER}.rpm https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/g/gengetopt-2.23-1.el7.x86_64.rpm sudo yum -y install ./gengetopt-${GENGETOPT_VER}.rpm export CMAKE="cmake" elif [ "$PLATFORM" == "centos8" ]; then sudo yum -y install epel-release sudo yum -y update && sudo yum -y upgrade sudo dnf group -y install "Development Tools" sudo dnf config-manager -y --set-enabled powertools sudo yum -y install chrpath \ git \ cmake3 \ gengetopt \ libedit-devel \ libcurl-devel \ libusbx-devel \ openssl-devel \ pcsc-lite-devel export CMAKE="cmake3" elif [ "${PLATFORM:0:6}" == "fedora" ]; then sudo dnf -y update sudo dnf -y install binutils \ git \ chrpath \ cmake \ gengetopt \ openssl-devel \ libusb-devel \ libedit-devel \ libcurl-devel \ rpmdevtools \ pcsc-lite-devel export CMAKE="cmake" fi export INPUT=/shared export OUTPUT=/shared/resources/release/linux/build/$PLATFORM/yubihsm-shell rm -rf $OUTPUT mkdir -p $OUTPUT # These 2 lines can be replaced by the command "rpmdev-setuptree", but this command seems to add macros that force check paths that do not exist mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros export RPM_DIR=~/rpmbuild cp /shared/resources/release/linux/yubihsm-shell.spec $RPM_DIR/SPECS/ QA_SKIP_BUILD_ROOT=1 rpmbuild -bb $RPM_DIR/SPECS/yubihsm-shell.spec cp $RPM_DIR/RPMS/x86_64/*.rpm $OUTPUT LICENSE_DIR="$OUTPUT/share/yubihsm-shell" mkdir -p $LICENSE_DIR pushd "/shared" &>/dev/null cp -r resources/release/linux/licenses $LICENSE_DIR/ for lf in $LICENSE_DIR/licenses/*; do chmod 644 $lf done pushd "$OUTPUT" &>/dev/null rm -f "yubihsm-shell-$PLATFORM-amd64.tar.gz" tar -C ".." -zcvf "../yubihsm-shell-$PLATFORM-amd64.tar.gz" "yubihsm-shell" rm -f *.rpm rm -rf licenses rm -rf ../yubihsm-shell popd &>/dev/null popd &>/dev/null yubihsm-shell-2.6.0/resources/release/linux/build-pkg.sh0000644000175100001770000000352414666527773022707 0ustar runnerdocker#!/usr/bin/env bash set -e -o pipefail set -x PLATFORM=$1 export DEBIAN_FRONTEND=noninteractive sudo apt-get update && sudo apt-get dist-upgrade -y sudo apt-get install -y build-essential \ chrpath \ git \ cmake \ pkg-config \ gengetopt \ help2man \ libedit-dev \ libcurl4-openssl-dev \ liblzma-dev \ libssl-dev \ libseccomp-dev \ libusb-1.0.0-dev \ dh-exec \ git-buildpackage \ curl \ libpcsclite-dev export INPUT=/shared/ export OUTPUT=/shared/resources/release/linux/build/$PLATFORM/yubihsm-shell rm -rf $OUTPUT mkdir -p $OUTPUT pushd "/tmp" &>/dev/null rm -rf yubihsm-shell git clone "$INPUT" yubihsm-shell pushd "yubihsm-shell" &>/dev/null if [ "${PLATFORM:0:6}" == "debian" ] || [ "$PLATFORM" == "ubuntu1804" ]; then dpkg-buildpackage -b --no-sign else dpkg-buildpackage fi popd &>/dev/null cp *.deb $OUTPUT popd &>/dev/null LICENSE_DIR="$OUTPUT/share/yubihsm-shell" mkdir -p $LICENSE_DIR pushd "/shared" &>/dev/null cp -r resources/release/linux/licenses $LICENSE_DIR/ for lf in $LICENSE_DIR/licenses/*; do chmod 644 $lf done pushd "$OUTPUT" &>/dev/null rm -f yubihsm-shell-$PLATFORM-amd64.tar.gz tar -C .. -zcvf ../yubihsm-shell-$PLATFORM-amd64.tar.gz yubihsm-shell rm -f *.deb rm -rf licenses rm -rf ../yubihsm-shell popd &>/dev/null popd &>/dev/nullyubihsm-shell-2.6.0/resources/release/linux/Vagrantfile0000644000175100001770000000670214666527773022663 0ustar runnerdocker# -*- mode: ruby -*- # vi: set ft=ruby : Vagrant.configure("2") do |config| config.vm.synced_folder ".", "/vagrant", disabled: true config.vm.provider "virtualbox" do |v| v.memory = 2048 v.cpus = 2 end config.vm.define "fedora36" do |fedora36| fedora36.vm.box = "generic/fedora36" fedora36.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--delete"] fedora36.vm.provision "shell", :path => "build-rpm.sh", :args => "fedora36", :privileged => false end config.vm.define "fedora37" do |fedora37| fedora37.vm.box = "generic/fedora37" fedora37.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--delete"] fedora37.vm.provision "shell", :path => "build-rpm.sh", :args => "fedora37", :privileged => false end config.vm.define "centos7" do |centos7| centos7.vm.box = "centos/7" centos7.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--copy-links"] centos7.vm.provision "shell", :path => "build-rpm.sh", :args => "centos7", :privileged => false end config.vm.define "debian10" do |debian10| debian10.vm.box = "roboxes/debian10" debian10.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--delete"] debian10.vm.provision "shell", :path => "build-pkg.sh", :args => "debian10", :privileged => false end config.vm.define "debian11" do |debian11| debian11.vm.box = "generic/debian11" debian11.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--delete"] debian11.vm.provision "shell", :path => "build-pkg.sh", :args => "debian11", :privileged => false end config.vm.define "trusty" do |trusty| trusty.vm.box = "ubuntu/trusty64" trusty.vm.synced_folder "../../..", "/shared" trusty.vm.provision "shell", :path => "build-pkg.sh", :args => "ubuntu1404", :privileged => false end config.vm.define "xenial" do |xenial| xenial.vm.box = "ubuntu/xenial64" xenial.vm.synced_folder "../../..", "/shared" xenial.vm.provision "shell", :path => "build-pkg.sh", :args => "ubuntu1604", :privileged => false end config.vm.define "bionic" do |bionic| bionic.vm.box = "ubuntu/bionic64" bionic.vm.synced_folder "../../..", "/shared" bionic.vm.provision "shell", :path => "build-pkg.sh", :args => "ubuntu1804", :privileged => false end config.vm.define "focal" do |focal| focal.vm.box = "generic/ubuntu2004" focal.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--copy-links"] focal.vm.provision "shell", :path => "build-pkg.sh", :args => "ubuntu2004", :privileged => false end config.vm.define "jammy" do |jammy| jammy.vm.box = "alvistack/ubuntu-22.04" jammy.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--copy-links"] jammy.vm.provision "shell", :path => "build-pkg.sh", :args => "ubuntu2204", :privileged => false end config.vm.define "kinetic" do |kinetic| kinetic.vm.box = "ubuntu/kinetic64" kinetic.vm.synced_folder "../../..", "/shared", type: "rsync", rsync__args: ["--verbose", "--archive", "-z", "--copy-links"] kinetic.vm.provision "shell", :path => "build-pkg.sh", :args => "ubuntu2210", :privileged => false end end yubihsm-shell-2.6.0/resources/release/linux/install_redhat_dependencies.sh0000755000175100001770000000522014666527773026532 0ustar runnerdocker#!/usr/bin/env bash set -e -o pipefail set -x PLATFORM=$1 if [ "$PLATFORM" == "centos7" ]; then yum -y install centos-release-scl yum -y update && yum -y upgrade # yum -y install devtoolset-7-gcc \ # devtoolset-7-gcc-c++ \ # devtoolset-7-make \ # chrpath \ # git \ # cmake \ # openssl-devel \ # libedit-devel \ # libcurl-devel \ # libusbx-devel \ # rpm-build \ # redhat-rpm-config \ # pcsc-lite-devel yum -y install gcc gcc-c++ \ cmake \ gengetopt \ openssl \ openssl-devel \ libedit-devel \ libcurl-devel \ libusbx-devel \ pcsc-lite-devel \ help2man \ chrpath \ rpm-build \ redhat-rpm-config # . /opt/rh/devtoolset-7/enable GENGETOPT_VER=2.23 #curl -o gengetopt-${GENGETOPT_VER}.rpm https://download-ib01.fedoraproject.org/pub/epel/7/x86_64/Packages/g/gengetopt-2.23-1.el7.x86_64.rpm curl -o gengetopt-${GENGETOPT_VER}.rpm https://dl.fedoraproject.org/pub/epel/7/x86_64/Packages/g/gengetopt-2.23-1.el7.x86_64.rpm yum -y install ./gengetopt-${GENGETOPT_VER}.rpm export CMAKE="cmake" elif [ "$PLATFORM" == "centos8" ]; then yum -y install epel-release yum -y update && yum -y upgrade dnf group -y install "Development Tools" dnf config-manager -y --set-enabled powertools yum -y install chrpath \ git \ cmake3 \ gengetopt \ libedit-devel \ libcurl-devel \ libusbx-devel \ openssl-devel \ pcsc-lite-devel export CMAKE="cmake3" elif [ "${PLATFORM:0:6}" == "fedora" ]; then dnf -y update dnf -y install binutils \ gcc \ gcc-c++ \ chrpath \ cmake \ gengetopt \ openssl-devel \ libedit-devel \ libcurl-devel \ rpmdevtools \ pcsc-lite-devel \ libusb1-devel \ help2man export CMAKE="cmake" fi yubihsm-shell-2.6.0/resources/release/macos/0000755000175100001770000000000014666527773020434 5ustar runnerdockeryubihsm-shell-2.6.0/resources/release/macos/distribution.xml0000644000175100001770000000144114666527773023675 0ustar runnerdocker yubihsm2-sdk yubihsm2-sdk.pkg yubihsm-shell-2.6.0/resources/release/macos/make_release_binaries.sh0000755000175100001770000000466414666527773025276 0ustar runnerdocker#!/usr/bin/env bash set -e -o pipefail set -x ARCH=$1 # amd or arm VERSION=$2 # Full yubico-piv-tool version, tex 2.1.0 SO_VERSION=$3 BREW_LIB="/opt/homebrew/opt" export PKG_CONFIG_PATH=$BREW_LIB/openssl/lib/pkgconfig SOURCE_DIR=$PWD MAC_DIR=$SOURCE_DIR/resources/release/macos OUTPUT=$MAC_DIR/yubihsm-shell-darwin-$ARCH-$VERSION/usr/local LICENSE_DIR=$OUTPUT/licenses cd $SOURCE_DIR mkdir build; cd build cmake -DRELEASE_BUILD=1 -DWITHOUT_YKYH=1 -DWITHOUT_MANPAGES=1 -DCMAKE_INSTALL_PREFIX="$OUTPUT/" .. make install cd $OUTPUT/lib ln -s "libcrypto.3.dylib" "libcrypto.dylib" cp "$BREW_LIB/openssl/lib/libcrypto.3.dylib" "$OUTPUT/lib" chmod +w "$OUTPUT/lib/libcrypto.3.dylib" cp -r $BREW_LIB/openssl/include/openssl "$OUTPUT/include" install_name_tool -id "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/lib/libcrypto.3.dylib" install_name_tool -change "$BREW_LIB/openssl@3/lib/libcrypto.3.dylib" "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/lib/libyubihsm.dylib" install_name_tool -change "$BREW_LIB/openssl@3/lib/libcrypto.3.dylib" "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/lib/libyubihsm.$VERSION.dylib" install_name_tool -change "$BREW_LIB/openssl/lib/libcrypto.3.dylib" "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/lib/libyubihsm.$SO_VERSION.dylib" install_name_tool -change "$BREW_LIB/libusb/lib/libusb-1.0.0.dylib" "@loader_path/../lib/libusb-1.0.0.dylib" "$OUTPUT/lib/libyubihsm_usb.dylib" install_name_tool -change "$BREW_LIB/libusb/lib/libusb-1.0.0.dylib" "@loader_path/../lib/libusb-1.0.0.dylib" "$OUTPUT/lib/libyubihsm_usb.$VERSION.dylib" install_name_tool -change "$BREW_LIB/libusb/lib/libusb-1.0.0.dylib" "@loader_path/../lib/libusb-1.0.0.dylib" "$OUTPUT/lib/libyubihsm_usb.$SO_VERSION.dylib" install_name_tool -change "$BREW_LIB/openssl/lib/libcrypto.3.dylib" "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/lib/pkcs11/yubihsm_pkcs11.dylib" install_name_tool -change "$BREW_LIB/openssl/lib/libcrypto.3.dylib" "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/bin/yubihsm-shell" install_name_tool -change "$BREW_LIB/openssl/lib/libcrypto.3.dylib" "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/bin/yubihsm-wrap" install_name_tool -change "$BREW_LIB/openssl/lib/libcrypto.3.dylib" "@loader_path/../lib/libcrypto.3.dylib" "$OUTPUT/bin/yubihsm-auth" for file in `find $OUTPUT/lib $OUTPUT/bin -type f`; do if otool -L $file | grep -q '$OUTPUT'; then echo "ERROR: $file is incorrectly linked, paths contain $OUTPUT" exit 1 fi doneyubihsm-shell-2.6.0/resources/release/macos/license.adoc0000644000175100001770000000026514666527773022711 0ustar runnerdockerBy clicking Continue you agree to the Yubico Toolset Software License Agreement located at https://www.yubico.com/support/terms-conditions/yubico-toolset-software-license-agreement/yubihsm-shell-2.6.0/resources/release/macos/make_installer.sh0000755000175100001770000000115214666527773023764 0ustar runnerdocker#!/bin/bash # Script to produce an OS X installer .pkg # This script has to be run from the source directory set -x ARCH=$1 SRC_PATH=$2 MAC_DIR=$PWD PKG_DIR=$MAC_DIR/pkg PKG_COMP=$PKG_DIR/comp PKG_RESOURCES=$PKG_DIR/resources/English.lproj mkdir -p $PKG_COMP $PKG_RESOURCES asciidoctor -o $PKG_RESOURCES/license.html $MAC_DIR/license.adoc pkgbuild --root="$SRC_PATH" --identifier "com.yubico.yubihsm2-sdk" "$PKG_COMP/yubihsm2-sdk.pkg" productbuild --package-path "$PKG_COMP" --distribution "$MAC_DIR/distribution.xml" --resources $PKG_RESOURCES "$MAC_DIR/yubihsm2-sdk-darwin-$ARCH.pkg" #clean up rm -rf $PKG_DIR yubihsm-shell-2.6.0/resources/release/macos/check_hardening.sh0000755000175100001770000000372714666527773024100 0ustar runnerdocker#!/bin/bash set -e -o pipefail -x YUBIHSM_SHELL_EXECUTABLE=$1 otool -hv $YUBIHSM_SHELL_EXECUTABLE # awk only looks at the fourth (last) output line of otool # the first line is the path to the file # the second line is simply 'Mach header' # the third line contains the column names otool -hv $YUBIHSM_SHELL_EXECUTABLE | awk 'NR == 4 { split($0, stdin_split, " "); flag_pie = 0; flag_allow_stack_execution = 0; flag_no_heap_execution = 0; # first 7 tokens are unrelated to the header flags # so we start looking tokens from the 8th position for (i = 8; i <= length(stdin_split); i++) { flag = stdin_split[i] if (flag == "PIE") { flag_pie = 1; } if (flag == "ALLOW_STACK_EXECUTION") { flag_allow_stack_execution = 1; } if (flag == "NO_HEAP_EXECUTION") { flag_no_heap_execution = 1; } } fail = 0; if (flag_pie == 0) { print "BINARY DOES NOT HAVE THE PIE FLAG"; fail = 1; } if (flag_allow_stack_execution == 1) { print "BINARY ALLOWS EXECUTION FROM THE STACK"; fail = 1; } if (flag_no_heap_execution == 0) { print "BINARY ALLOWS EXECUTION FROM THE HEAP"; # currently we do not treat this as an error } if (fail == 1) { exit 1; } }' if [ $? = 1 ]; then exit 1 fi check_import() { nm -u $YUBIHSM_SHELL_EXECUTABLE | grep $1 >/dev/null # return code of grep is 0 when it finds something if [ $? == 0 ]; then echo 1 else echo 0 fi } chk_fail=$(check_import '___stack_chk_fail') chk_guard=$(check_import '___stack_chk_guard') if [ $chk_fail = 0 ] | [ $chk_guard = 0 ]; then echo "BINARY DOES NOT HAVE STACK CANARIES" exit 1 fi yubihsm-shell-2.6.0/resources/release/win/0000755000175100001770000000000014666527773020127 5ustar runnerdockeryubihsm-shell-2.6.0/resources/release/win/sign_installer.bat0000644000175100001770000000044714666527773023641 0ustar runnerdockerSETLOCAL set CERTHASH="107533FA07911D8BB375459B804DABA89CC61E77" set SIGNCMD=signtool sign /ph /fd "SHA256" /sha1 %CERTHASH% /t "http://timestamp.digicert.com" %SIGNCMD% /d "YubiHSM Shell Installer (x64)" yubihsm-shell-x64.msi %SIGNCMD% /d "YubiHSM Shell Installer (x86)" yubihsm-shell-x86.msiyubihsm-shell-2.6.0/resources/release/win/yubihsm-shell_x64.wxs0000644000175100001770000000657714666527773024177 0ustar runnerdocker 1 1 2 yubihsm-shell-2.6.0/resources/release/win/sign_release.bat0000644000175100001770000000304314666527773023257 0ustar runnerdockerSETLOCAL set CERTHASH="107533FA07911D8BB375459B804DABA89CC61E77" set CERTHASHSTD="DD86A2E1383B0E4E1C823B606DDBBCC26E1FF82D" set SIGNCMD=signtool sign /ph /fd "SHA256" /sha1 %CERTHASH% /t "http://timestamp.digicert.com" set SIGNCMDSTD=signtool sign /ph /fd "SHA256" /sha1 %CERTHASHSTD% /t "http://timestamp.digicert.com" rem Sign x64 components %SIGNCMD% yubihsm-shell-x64\bin\libyubihsm.dll %SIGNCMD% yubihsm-shell-x64\bin\libyubihsm_http.dll %SIGNCMD% yubihsm-shell-x64\bin\libyubihsm_usb.dll %SIGNCMD% yubihsm-shell-x64\bin\pkcs11\yubihsm_pkcs11.dll %SIGNCMD% yubihsm-shell-x64\bin\ykhsmauth.dll %SIGNCMD% /d "YubiHSM Authenication" yubihsm-shell-x64\bin\yubihsm-auth.exe %SIGNCMD% /d "YubiHSM Shell" yubihsm-shell-x64\bin\yubihsm-shell.exe %SIGNCMD% /d "YubiHSM Wrap" yubihsm-shell-x64\bin\yubihsm-wrap.exe rem Sign x86 components %SIGNCMD% yubihsm-shell-x86\bin\libyubihsm.dll %SIGNCMD% yubihsm-shell-x86\bin\libyubihsm_http.dll %SIGNCMD% yubihsm-shell-x86\bin\libyubihsm_usb.dll %SIGNCMD% yubihsm-shell-x86\bin\pkcs11\yubihsm_pkcs11.dll %SIGNCMD% yubihsm-shell-x86\bin\ykhsmauth.dll %SIGNCMD% /d "YubiHSM Authenication" yubihsm-shell-x86\bin\yubihsm-auth.exe %SIGNCMD% /d "YubiHSM Shell" yubihsm-shell-x86\bin\yubihsm-shell.exe %SIGNCMD% /d "YubiHSM Wrap" yubihsm-shell-x86\bin\yubihsm-wrap.exe rem Sign "standard open source" components (not from Yubico Source) %SIGNCMDSTD% yubihsm-shell-x64\bin\getopt.dll %SIGNCMDSTD% yubihsm-shell-x64\bin\libcrypto-3-x64.dll %SIGNCMDSTD% yubihsm-shell-x86\bin\getopt.dll %SIGNCMDSTD% yubihsm-shell-x86\bin\libcrypto-3.dll yubihsm-shell-2.6.0/resources/release/win/yubihsm-shell_x86.wxs0000644000175100001770000000656314666527773024176 0ustar runnerdocker 1 1 2 yubihsm-shell-2.6.0/resources/release/win/license.rtf0000644000175100001770000000110214666527773022260 0ustar runnerdocker{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}} {\colortbl ;\red0\green0\blue255;} {\*\generator Riched20 10.0.18362}\viewkind4\uc1 \pard\sa200\sl276\slmult1\f0\fs22\lang9 By clicking Next you agree to the Yubico Toolset Software License Agreement located at {{\field{\*\fldinst{HYPERLINK https://www.yubico.com/support/terms-conditions/yubico-toolset-software-license-agreement/ }}{\fldrslt{https://www.yubico.com/support/terms-conditions/yubico-toolset-software-license-agreement/\ul0\cf0}}}}\f0\fs22\par \par \par \par } yubihsm-shell-2.6.0/resources/release/win/make_release_binaries.ps10000644000175100001770000000507314666527773025052 0ustar runnerdockerif($args.length -lt 2) { echo "Usage: ./make_installer.ps1 " echo "" echo "This is a script to build an MSI installer for yubihsm" echo "" echo " Win32 builds using X86 architecture by adding '-A Win32' argument to the cmake command" echo " x64 builds using X64 architecture by adding '-A x64' argument to the cmake command" echo "" echo " VCPKG_PATH Absolute path to the directory where vcpkg.exe is located" exit } $CMAKE_ARCH=$args[0] $VCPKG_PATH=$args[1] if($CMAKE_ARCH -eq "Win32") { $ARCH="x86" } else { $ARCH="x64" } $WIN_DIR = "$PSScriptRoot" $SOURCE_DIR="$PSScriptRoot/../../.." $BUILD_DIR="$WIN_DIR/build_release" $RELEASE_DIR="$WIN_DIR/yubihsm-shell-$ARCH" $LICENSES_DIR="$RELEASE_DIR/licenses" Set-PSDebug -Trace 1 # Install prerequisites cd $VCPKG_PATH .\vcpkg.exe update .\vcpkg.exe install openssl:$ARCH-windows .\vcpkg.exe install getopt:$ARCH-windows $env:OPENSSL_ROOT_DIR ="$VCPKG_PATH/packages/openssl_$ARCH-windows" # Build binaries mkdir $BUILD_DIR; cd $BUILD_DIR cmake -S $SOURCE_DIR -A "$CMAKE_ARCH" -DGETOPT_LIB_DIR="$VCPKG_PATH/packages/getopt-win32_$ARCH-windows/lib" -DGETOPT_INCLUDE_DIR="$VCPKG_PATH/packages/getopt-win32_$ARCH-windows/include" -DCMAKE_INSTALL_PREFIX="$RELEASE_DIR" cmake --build . --config Release --target install # Copy openssl and getopt libraries cd $RELEASE_DIR/bin if($ARCH -eq "x86") { cp $VCPKG_PATH/packages/openssl_x86-windows/bin/libcrypto-3.dll . cp $VCPKG_PATH/packages/getopt-win32_x86-windows/bin/getopt.dll . } else { cp $VCPKG_PATH/packages/openssl_x64-windows/bin/libcrypto-3-x64.dll . cp $VCPKG_PATH/packages/getopt-win32_x64-windows/bin/getopt.dll . } # Create missing directories Remove-Item -Path $LICENSES_DIR -Force -Recurse -ErrorAction SilentlyContinue mkdir -p $LICENSES_DIR # Copy licenses $license=(Get-ChildItem -Path $SOURCE_DIR -Filter LICENSE -Recurse -ErrorAction SilentlyContinue -Force | %{$_.FullName}) cp $license $LICENSES_DIR/yubihsm-shell.txt $license=(Get-ChildItem -Path $VCPKG_PATH\buildtrees\openssl\src\ -Filter LICENSE -Recurse -ErrorAction SilentlyContinue -Force | %{$_.FullName}) cp $license $LICENSES_DIR\openssl.txt $license=(Get-ChildItem -Path $VCPKG_PATH\buildtrees\getopt-win32\src\ -Filter LICENSE -Recurse -ErrorAction SilentlyContinue -Force | %{$_.FullName}) cp $license $LICENSES_DIR\getopt.txt #cd $WIN_DIR #Compress-Archive -LiteralPath "$WIN_DIR/yubihsm-shell-$ARCH" -DestinationPath "$WIN_DIR/yubihsm-shell-$ARCH.zip" rm -r $BUILD_DIR Set-PSDebug -Trace 0 yubihsm-shell-2.6.0/resources/release/win/repack_installer.ps10000644000175100001770000000343514666527773024103 0ustar runnerdockerif($args.length -lt 3) { echo "Usage: ./repack_installer.ps1 []" echo "" echo "This is a script to build an MSI installer for yubihsm" echo "" echo " x86 builds the installer for X86 architecture" echo " x64 builds the installer for X64 architecture" echo "" echo " WIX_PATH Absolute path to the directory where WIX Tools binaries (heat.exe, candle.exe and light.exe) are located" echo " MERGE_MODULE_PATH Absolute path to the redistribution module (tex Microsoft_VC142_CRT_x86.msm or Microsoft_VC142_CRT_x64.msm)" echo " SIGNED_BINARIES_PATH (Optional) Absolute path to signed binaries. If not spacified, YUBIHSM-SHELL/resources/release/win/yubihsm-shell-[x86|x64] is assumed" exit } $ARCH=$args[0] $WIX_PATH=$args[1] # Absolute path to the WixTools binaries $MERGE_MODULE=$args[2] # Absolute path containing Microsoft_VC142_CRT_x86.msm or Microsoft_VC142_CRT_x64.msm $WIN_DIR = "$PSScriptRoot" $SOURCE_DIR="$PSScriptRoot/../../.." if($args.length -eq 4) { $RELEASE_DIR=$args[3] } else { $RELEASE_DIR="$WIN_DIR/yubihsm-shell-$ARCH" } Set-PSDebug -Trace 1 # Build MSI cd $WIN_DIR $env:PATH += ";$WIX_PATH" $env:SRCDIR = $RELEASE_DIR $env:MERGEDPATH = $MERGE_MODULE heat.exe dir $RELEASE_DIR -out fragment.wxs -gg -scom -srd -sfrag -sreg -dr INSTALLDIR -cg ApplicationFiles -var env.SRCDIR candle.exe fragment.wxs "yubihsm-shell_$ARCH.wxs" -ext WixUtilExtension -arch $ARCH light.exe fragment.wixobj "yubihsm-shell_$ARCH.wixobj" -ext WixUIExtension -ext WixUtilExtension -o "yubihsm-shell-$ARCH.msi" #cleanup rm fragment.wxs rm fragment.wixobj rm "yubihsm-shell_$ARCH.wixobj" rm "yubihsm-shell-$ARCH.wixpdb" Set-PSDebug -Trace 0 yubihsm-shell-2.6.0/yubihsm-auth/0000755000175100001770000000000014666530033016276 5ustar runnerdockeryubihsm-shell-2.6.0/yubihsm-auth/CMakeLists.txt0000644000175100001770000000477014666527773021067 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() set ( SOURCE main.c ../common/parsing.c ../common/pkcs5.c ../common/hash.c ) if(WIN32) set(SOURCE ${SOURCE} cmdline.c) include(${CMAKE_SOURCE_DIR}/cmake/getopt.cmake) find_getopt() else(WIN32) include(gengetopt) add_gengetopt_files (cmdline) set(SOURCE ${SOURCE} ${GGO_C}) message("${GGO_C}") endif(WIN32) include_directories ( ${LIBCRYPTO_INCLUDEDIR} ${CMAKE_CURRENT_SOURCE_DIR}/../ykhsmauth ${CMAKE_CURRENT_SOURCE_DIR}/../common ) if(WIN32) list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) set (BCRYPT_LIBRARY bcrypt) endif(WIN32) # NOTE(adma): required by gengetopt add_definitions (-DPACKAGE="yubihsm-auth") add_definitions (-DVERSION="${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") list(APPEND LCOV_REMOVE_PATTERNS "'${PROJECT_SOURCE_DIR}/yubihsm-auth/cmdline.c'") if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") set_property(SOURCE ${GGO_C} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unused-but-set-variable ") endif() add_executable (yubihsm-auth ${SOURCE}) target_link_libraries ( yubihsm-auth ${LIBCRYPTO_LDFLAGS} ${GETOPT_LIBS} ykhsmauth ${BCRYPT_LIBRARY} ) # Set install RPATH set_target_properties(yubihsm-auth PROPERTIES INSTALL_RPATH "${YUBIHSM_INSTALL_LIB_DIR}") install( TARGETS yubihsm-auth ARCHIVE DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" RUNTIME DESTINATION "${YUBIHSM_INSTALL_BIN_DIR}") if (NOT WITHOUT_MANPAGES) include (help2man) add_help2man_manpage (yubihsm-auth.1 yubihsm-auth) add_custom_target (yubihsm-auth-man ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/yubihsm-auth.1 ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/yubihsm-auth.1" DESTINATION "${YUBIHSM_INSTALL_MAN_DIR}/man1") endif () yubihsm-shell-2.6.0/yubihsm-auth/main.c0000644000175100001770000004306014666527773017412 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include "pkcs5.h" #include "parsing.h" #include "cmdline.h" static bool parse_label(const char *prompt, char *label, char *parsed, size_t *parsed_len) { if (strlen(label) > *parsed_len) { fprintf(stdout, "Unable to read label, buffer too small\n"); return false; } if (strlen(label) == 0) { if (read_string(prompt, parsed, *parsed_len, false) == false) { return false; } } else { strcpy(parsed, label); } *parsed_len = strlen(parsed); return true; } static bool parse_pw(const char *prompt, char *pw, uint8_t *parsed, size_t *parsed_len) { if (strlen(pw) == 0) { if (read_string(prompt, (char *) parsed, *parsed_len, HIDDEN_CHECKED) == false) { return false; } } else { if(strcmp(pw, "-")) { if (strlen(pw) > *parsed_len) { fprintf(stderr, "Unable to read password, buffer too small\n"); return false; } strncpy((char *) parsed, pw, *parsed_len); } else { *parsed = 0; } } *parsed_len = strlen((char *) parsed); return true; } static bool parse_key(const char *prompt, char *key, uint8_t *parsed, size_t *parsed_len) { char buf[320] = {0}; size_t buf_size = sizeof(buf); size_t initial_len = *parsed_len; if (strlen(key) > buf_size) { fprintf(stdout, "Unable to read %s, buffer too small\n", prompt); return false; } if (strlen(key) == 0) { if (read_string(prompt, buf, buf_size, true) == false) { return false; } } else { strcpy(buf, key); } buf_size = strlen(buf); if (hex_decode(buf, parsed, parsed_len) == false) { fprintf(stdout, "Unable to parse %s, must be %d characters hexadecimal\n", prompt, YKHSMAUTH_YUBICO_AES128_KEY_LEN); return false; } if (*parsed_len != initial_len) { fprintf(stdout, "Unable to read %s, wrong length (must be %zu)\n", prompt, initial_len); return false; } return true; } static bool parse_context(const char *prompt, char *context, uint8_t *parsed, size_t *parsed_len) { char buf[320] = {0}; size_t buf_size = sizeof(buf); size_t initial_len = *parsed_len; if (strlen(context) > buf_size) { fprintf(stdout, "Unable to read context, buffer too small\n"); return false; } if (strlen(context) == 0) { if (read_string(prompt, buf, buf_size, false) == false) { return false; } buf_size = strlen(buf); } else { memcpy(buf, context, strlen(context)); buf_size = strlen(context); } if (hex_decode(buf, parsed, parsed_len) == false) { fprintf(stdout, "Unable to parse context, must be %d characters hexadecimal\n", YKHSMAUTH_CONTEXT_LEN * 2); return false; } if (*parsed_len != initial_len) { fprintf(stdout, "Unable to read context, wrong length (must be %d)\n", YKHSMAUTH_CONTEXT_LEN); return false; } return true; } static bool parse_touch_policy(enum enum_touch touch_policy, uint8_t *touch_policy_parsed) { switch (touch_policy) { case touch__NULL: case touch_arg_off: *touch_policy_parsed = 0; break; case touch_arg_on: *touch_policy_parsed = 1; break; } return true; } static bool delete_credential(ykhsmauth_state *state, char *mgmkey, char *label) { uint8_t mgmkey_parsed[YKHSMAUTH_PW_LEN] = {0}; size_t mgmkey_parsed_len = sizeof(mgmkey_parsed); char label_parsed[YKHSMAUTH_MAX_LABEL_LEN + 2] = {0}; size_t label_parsed_len = sizeof(label_parsed); uint8_t retries = 0; if (parse_key("Management key", mgmkey, mgmkey_parsed, &mgmkey_parsed_len) == false) { return false; } if (parse_label("Label", label, label_parsed, &label_parsed_len) == false) { return false; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_delete(state, mgmkey_parsed, mgmkey_parsed_len, label_parsed, &retries); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to delete credential: %s, %d retries left\n", ykhsmauth_strerror(ykhsmauthrc), retries); return false; } fprintf(stdout, "Credential successfully deleted\n"); return true; } static bool list_credentials(ykhsmauth_state *state) { ykhsmauth_list_entry list[32] = {0}; size_t list_items = sizeof(list) / sizeof(list[0]); ykhsmauth_rc ykhsmauthrc = ykhsmauth_list_keys(state, list, &list_items); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to list credentials: %s\n", ykhsmauth_strerror(ykhsmauthrc)); return false; } if (list_items == 0) { fprintf(stdout, "No items found\n"); return true; } fprintf(stdout, "Found %zu item(s)\n", list_items); fprintf(stdout, "Algo\tTouch\tCounter\tLabel\n"); for (size_t i = 0; i < list_items; i++) { fprintf(stdout, "%d\t%d\t%d\t%s\n", list[i].algo, list[i].touch, list[i].ctr, list[i].label); } return true; } static bool put_credential(ykhsmauth_state *state, char *mgmkey, char *label, char *derivation_password, char *key_enc, char *key_mac, char *key_priv, char *credpassword, enum enum_touch touch_policy) { uint8_t mgmkey_parsed[YKHSMAUTH_PW_LEN] = {0}; size_t mgmkey_parsed_len = sizeof(mgmkey_parsed); char label_parsed[YKHSMAUTH_MAX_LABEL_LEN + 2] = {0}; size_t label_parsed_len = sizeof(label_parsed); uint8_t dpw_parsed[256] = {0}; size_t dpw_parsed_len = sizeof(dpw_parsed); uint8_t key_parsed[YKHSMAUTH_YUBICO_ECP256_PUBKEY_LEN] = {0}; size_t key_parsed_len = sizeof(key_parsed); uint8_t cpw_parsed[YKHSMAUTH_PW_LEN + 2] = {0}; size_t cpw_parsed_len = sizeof(cpw_parsed); uint8_t touch_policy_parsed = 0; uint8_t retries = 0; if (parse_key("Management key", mgmkey, mgmkey_parsed, &mgmkey_parsed_len) == false) { return false; } if (parse_label("Label", label, label_parsed, &label_parsed_len) == false) { return false; } if (strlen(key_mac) == 0 && strlen(key_enc) == 0 && strlen(key_priv) == 0) { if (parse_pw("Derivation password", derivation_password, dpw_parsed, &dpw_parsed_len) == false) { return false; } } else { dpw_parsed_len = 0; } if (dpw_parsed_len == 0) { if (strlen(key_priv)) { if (strcmp(key_priv, "-")) { key_parsed_len = YKHSMAUTH_YUBICO_ECP256_PRIVKEY_LEN; if (parse_key("Private key", key_priv, key_parsed, &key_parsed_len) == false) { return false; } } else { key_parsed_len = 0; } } else { size_t key_enc_parsed_len = YKHSMAUTH_YUBICO_AES128_KEY_LEN / 2; size_t key_mac_parsed_len = YKHSMAUTH_YUBICO_AES128_KEY_LEN / 2; if (parse_key("Encryption key", key_enc, key_parsed, &key_enc_parsed_len) == false) { return false; } if (parse_key("MAC key", key_mac, key_parsed + key_enc_parsed_len, &key_mac_parsed_len) == false) { return false; } key_parsed_len = key_enc_parsed_len + key_mac_parsed_len; } } else { if (pkcs5_pbkdf2_hmac((uint8_t *) dpw_parsed, dpw_parsed_len, (const uint8_t *) YKHSMAUTH_DEFAULT_SALT, strlen(YKHSMAUTH_DEFAULT_SALT), YKHSMAUTH_DEFAULT_ITERS, _SHA256, key_parsed, YKHSMAUTH_YUBICO_AES128_KEY_LEN) == false) { return false; } key_parsed_len = YKHSMAUTH_YUBICO_AES128_KEY_LEN; } if (parse_pw("Credential Password (max 16 characters)", credpassword, cpw_parsed, &cpw_parsed_len) == false) { return false; } if (cpw_parsed_len > YKHSMAUTH_PW_LEN) { fprintf(stderr, "Credential password can not be more than %d characters.\n", YKHSMAUTH_PW_LEN); return false; } if (parse_touch_policy(touch_policy, &touch_policy_parsed) == false) { return false; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_put(state, mgmkey_parsed, mgmkey_parsed_len, label_parsed, strlen(key_priv) ? YKHSMAUTH_YUBICO_ECP256_ALGO : YKHSMAUTH_YUBICO_AES128_ALGO, key_parsed, key_parsed_len, cpw_parsed, cpw_parsed_len, touch_policy_parsed, &retries); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to store credential: %s, %d retries left\n", ykhsmauth_strerror(ykhsmauthrc), retries); return false; } fprintf(stdout, "Credential successfully stored\n"); return true; } static bool reset_device(ykhsmauth_state *state) { ykhsmauth_rc ykhsmauthrc = ykhsmauth_reset(state); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to reset device: %s\n", ykhsmauth_strerror(ykhsmauthrc)); return false; } fprintf(stdout, "Device successfully reset\n"); return true; } static bool get_mgmkey_retries(ykhsmauth_state *state) { uint8_t retries = 0; ykhsmauth_rc ykhsmauthrc = ykhsmauth_get_mgmkey_retries(state, &retries); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to get mgmkey retries: %s\n", ykhsmauth_strerror(ykhsmauthrc)); return false; } fprintf(stdout, "Retries left for Management Key: %d\n", retries); return true; } static void print_key(char *prompt, uint8_t *key, size_t len) { fprintf(stdout, "%s: ", prompt); for (size_t i = 0; i < len; i++) { fprintf(stdout, "%02x", key[i]); } fprintf(stdout, "\n"); } static bool get_challenge(ykhsmauth_state *state, char *label, char *credpassword) { char label_parsed[YKHSMAUTH_MAX_LABEL_LEN + 2] = {0}; size_t label_parsed_len = sizeof(label_parsed); uint8_t cpw_parsed[YKHSMAUTH_PW_LEN + 2] = {0}; size_t cpw_parsed_len = sizeof(cpw_parsed); uint8_t challenge[YKHSMAUTH_YUBICO_ECP256_PUBKEY_LEN] = {0}; size_t challenge_len = sizeof(challenge); if (parse_label("Label", label, label_parsed, &label_parsed_len) == false) { return false; } if (parse_pw("Credential Password (max 16 characters)", credpassword, cpw_parsed, &cpw_parsed_len) == false) { return false; } if (cpw_parsed_len > YKHSMAUTH_PW_LEN) { fprintf(stderr, "Credential password can not be more than %d characters.\n", YKHSMAUTH_PW_LEN); return false; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_get_challenge_ex(state, label_parsed, cpw_parsed, cpw_parsed_len, challenge, &challenge_len); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to get challenge: %s\n", ykhsmauth_strerror(ykhsmauthrc)); return false; } print_key("Challenge", challenge, challenge_len); return true; } static bool get_pubkey(ykhsmauth_state *state, char *label) { char label_parsed[YKHSMAUTH_MAX_LABEL_LEN + 2] = {0}; size_t label_parsed_len = sizeof(label_parsed); uint8_t pubkey[YKHSMAUTH_YUBICO_ECP256_PUBKEY_LEN] = {0}; size_t pubkey_len = sizeof(pubkey); if (parse_label("Label", label, label_parsed, &label_parsed_len) == false) { return false; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_get_pubkey(state, label_parsed, pubkey, &pubkey_len); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to get pubkey: %s\n", ykhsmauth_strerror(ykhsmauthrc)); return false; } print_key("Long-term public key", pubkey, pubkey_len); return true; } static bool get_version(ykhsmauth_state *state) { char version[64] = {0}; size_t version_len = sizeof(version); ykhsmauth_rc ykhsmauthrc = ykhsmauth_get_version(state, version, version_len); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to get version: %s\n", ykhsmauth_strerror(ykhsmauthrc)); return false; } fprintf(stdout, "Version %s\n", version); return true; } static bool calculate_session_keys(ykhsmauth_state *state, char *label, char *credpassword, char *context) { char label_parsed[YKHSMAUTH_MAX_LABEL_LEN + 2] = {0}; size_t label_parsed_len = sizeof(label_parsed); uint8_t context_parsed[YKHSMAUTH_CONTEXT_LEN] = {0}; size_t context_parsed_len = sizeof(context_parsed); uint8_t cpw_parsed[YKHSMAUTH_PW_LEN + 2] = {0}; size_t cpw_parsed_len = sizeof(cpw_parsed); uint8_t key_s_enc[YKHSMAUTH_SESSION_KEY_LEN] = {0}; uint8_t key_s_mac[YKHSMAUTH_SESSION_KEY_LEN] = {0}; uint8_t key_s_rmac[YKHSMAUTH_SESSION_KEY_LEN] = {0}; size_t key_s_enc_len = sizeof(key_s_enc); size_t key_s_mac_len = sizeof(key_s_mac); size_t key_s_rmac_len = sizeof(key_s_rmac); uint8_t retries = 0; if (parse_label("Label", label, label_parsed, &label_parsed_len) == false) { return false; } if (parse_context("Context", context, context_parsed, &context_parsed_len) == false) { return false; } if (parse_pw("Credential password", credpassword, cpw_parsed, &cpw_parsed_len) == false) { return false; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_calculate(state, label_parsed, context_parsed, context_parsed_len, cpw_parsed, cpw_parsed_len, key_s_enc, key_s_enc_len, key_s_mac, key_s_mac_len, key_s_rmac, key_s_rmac_len, &retries); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to calculate session keys: %s\n", ykhsmauth_strerror(ykhsmauthrc)); if (ykhsmauthrc == YKHSMAUTHR_WRONG_PW) { fprintf(stderr, "%d attempts left\n", retries); } return false; } print_key("Session encryption key", key_s_enc, key_s_enc_len); print_key("Session MAC key", key_s_mac, key_s_mac_len); print_key("Session R-MAC key", key_s_rmac, key_s_rmac_len); return true; } static bool put_mgmkey(ykhsmauth_state *state, char *mgmkey, char *new_mgmkey) { uint8_t mgmkey_parsed[YKHSMAUTH_PW_LEN] = {0}; size_t mgmkey_parsed_len = sizeof(mgmkey_parsed); uint8_t new_mgmkey_parsed[YKHSMAUTH_PW_LEN] = {0}; size_t new_mgmkey_parsed_len = sizeof(mgmkey_parsed); uint8_t retries = 0; if (parse_key("Management key", mgmkey, mgmkey_parsed, &mgmkey_parsed_len) == false) { return false; } if (parse_key("New Management key", new_mgmkey, new_mgmkey_parsed, &new_mgmkey_parsed_len) == false) { return false; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_put_mgmkey(state, mgmkey_parsed, mgmkey_parsed_len, new_mgmkey_parsed, new_mgmkey_parsed_len, &retries); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to change Management key: %s, %d retries left\n", ykhsmauth_strerror(ykhsmauthrc), retries); return false; } fprintf(stdout, "Management key successfully changed\n"); return true; } int main(int argc, char *argv[]) { struct gengetopt_args_info args_info = {0}; ykhsmauth_state *state = NULL; int rc = EXIT_FAILURE; if (cmdline_parser(argc, argv, &args_info) != 0) { goto main_exit; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_init(&state, args_info.verbose_arg); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Failed to initialize libykhsmauth\n"); goto main_exit; } ykhsmauthrc = ykhsmauth_connect(state, args_info.reader_arg); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Unable to connect: %s\n", ykhsmauth_strerror(ykhsmauthrc)); goto main_exit; } bool result = false; switch (args_info.action_arg) { case action_arg_calculate: result = calculate_session_keys(state, args_info.label_arg, args_info.credpwd_arg, args_info.context_arg); break; case action_arg_changeMINUS_mgmkey: result = put_mgmkey(state, args_info.mgmkey_arg, args_info.new_mgmkey_arg); break; case action_arg_delete: result = delete_credential(state, args_info.mgmkey_arg, args_info.label_arg); break; case action_arg_list: result = list_credentials(state); break; case action_arg_put: result = put_credential(state, args_info.mgmkey_arg, args_info.label_arg, args_info.derivation_password_arg, args_info.enckey_arg, args_info.mackey_arg, args_info.privkey_arg, args_info.credpwd_arg, args_info.touch_arg); break; case action_arg_reset: result = reset_device(state); break; case action_arg_retries: result = get_mgmkey_retries(state); break; case action_arg_getMINUS_challenge: result = get_challenge(state, args_info.label_arg, args_info.credpwd_arg); break; case action_arg_getMINUS_pubkey: result = get_pubkey(state, args_info.label_arg); break; case action_arg_version: result = get_version(state); break; case action__NULL: fprintf(stderr, "No action given, nothing to do\n"); break; } if (result == true) { rc = EXIT_SUCCESS; } main_exit: ykhsmauth_done(state); return rc; } yubihsm-shell-2.6.0/yubihsm-auth/cmdline.ggo0000644000175100001770000000417214666527773020434 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # option "action" a "Action to perform" values="calculate", "change-mgmkey", "delete", "list", "put", "reset", "retries", "version", "get-challenge", "get-pubkey" enum optional option "mgmkey" k "Management key is required to put and delete credentials. Sometimes, this key is also referenced as 'Admin Access Code'" string optional default="00000000000000000000000000000000" option "new-mgmkey" K "New management key" string optional default="" option "credpwd" p "Credential password is used to access the credential when logging into the YubiHSM2. Sometimes, this password is also referenced as 'User Access Code'" string optional default="" option "label" l "Credential label" string optional default="" option "reader" r "Only use a matching reader" string optional default="" option "touch" t "Touch required" values="off","on" enum optional default="off" option "context" c "Session keys calculation context" string optional default="" option "verbose" v "Print more information" int optional default="0" argoptional defmode "derivation" modedesc="Derive keys from a password using PBKDF2" modeoption "derivation-password" d "Derivation password for encryption and MAC keys" string mode="derivation" optional default="" defmode "explicit" modedesc="Explicit encryption and MAC keys" modeoption "enckey" e "Encryption key" string optional default="" mode="explicit" modeoption "mackey" m "MAC key" string optional default="" mode="explicit" defmode "asymmetric" modedesc="Explicit ec-p256 private key" modeoption "privkey" s "Private key" string optional default="" mode="asymmetric" yubihsm-shell-2.6.0/yubihsm-auth/cmdline.h0000644000175100001770000002727614666530033020100 0ustar runnerdocker/** @file cmdline.h * @brief The header file for the command line option parser * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten * @author GNU Gengetopt */ #ifndef CMDLINE_H #define CMDLINE_H /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* for FILE */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CMDLINE_PARSER_PACKAGE /** @brief the program name (used for printing errors) */ #define CMDLINE_PARSER_PACKAGE PACKAGE #endif #ifndef CMDLINE_PARSER_PACKAGE_NAME /** @brief the complete program name (used for help and version) */ #ifdef PACKAGE_NAME #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE_NAME #else #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE #endif #endif #ifndef CMDLINE_PARSER_VERSION /** @brief the program version */ #define CMDLINE_PARSER_VERSION VERSION #endif enum enum_action { action__NULL = -1, action_arg_calculate = 0, action_arg_changeMINUS_mgmkey, action_arg_delete, action_arg_list, action_arg_put, action_arg_reset, action_arg_retries, action_arg_version, action_arg_getMINUS_challenge, action_arg_getMINUS_pubkey }; enum enum_touch { touch__NULL = -1, touch_arg_off = 0, touch_arg_on }; /** @brief Where the command line options are stored */ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ enum enum_action action_arg; /**< @brief Action to perform. */ char * action_orig; /**< @brief Action to perform original value given at command line. */ const char *action_help; /**< @brief Action to perform help description. */ char * mgmkey_arg; /**< @brief Management key is required to put and delete credentials. Sometimes, this key is also referenced as 'Admin Access Code' (default='00000000000000000000000000000000'). */ char * mgmkey_orig; /**< @brief Management key is required to put and delete credentials. Sometimes, this key is also referenced as 'Admin Access Code' original value given at command line. */ const char *mgmkey_help; /**< @brief Management key is required to put and delete credentials. Sometimes, this key is also referenced as 'Admin Access Code' help description. */ char * new_mgmkey_arg; /**< @brief New management key (default=''). */ char * new_mgmkey_orig; /**< @brief New management key original value given at command line. */ const char *new_mgmkey_help; /**< @brief New management key help description. */ char * credpwd_arg; /**< @brief Credential password is used to access the credential when logging into the YubiHSM2. Sometimes, this password is also referenced as 'User Access Code' (default=''). */ char * credpwd_orig; /**< @brief Credential password is used to access the credential when logging into the YubiHSM2. Sometimes, this password is also referenced as 'User Access Code' original value given at command line. */ const char *credpwd_help; /**< @brief Credential password is used to access the credential when logging into the YubiHSM2. Sometimes, this password is also referenced as 'User Access Code' help description. */ char * label_arg; /**< @brief Credential label (default=''). */ char * label_orig; /**< @brief Credential label original value given at command line. */ const char *label_help; /**< @brief Credential label help description. */ char * reader_arg; /**< @brief Only use a matching reader (default=''). */ char * reader_orig; /**< @brief Only use a matching reader original value given at command line. */ const char *reader_help; /**< @brief Only use a matching reader help description. */ enum enum_touch touch_arg; /**< @brief Touch required (default='off'). */ char * touch_orig; /**< @brief Touch required original value given at command line. */ const char *touch_help; /**< @brief Touch required help description. */ char * context_arg; /**< @brief Session keys calculation context (default=''). */ char * context_orig; /**< @brief Session keys calculation context original value given at command line. */ const char *context_help; /**< @brief Session keys calculation context help description. */ int verbose_arg; /**< @brief Print more information (default='0'). */ char * verbose_orig; /**< @brief Print more information original value given at command line. */ const char *verbose_help; /**< @brief Print more information help description. */ char * derivation_password_arg; /**< @brief Derivation password for encryption and MAC keys (default=''). */ char * derivation_password_orig; /**< @brief Derivation password for encryption and MAC keys original value given at command line. */ const char *derivation_password_help; /**< @brief Derivation password for encryption and MAC keys help description. */ char * enckey_arg; /**< @brief Encryption key (default=''). */ char * enckey_orig; /**< @brief Encryption key original value given at command line. */ const char *enckey_help; /**< @brief Encryption key help description. */ char * mackey_arg; /**< @brief MAC key (default=''). */ char * mackey_orig; /**< @brief MAC key original value given at command line. */ const char *mackey_help; /**< @brief MAC key help description. */ char * privkey_arg; /**< @brief Private key (default=''). */ char * privkey_orig; /**< @brief Private key original value given at command line. */ const char *privkey_help; /**< @brief Private key help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int action_given ; /**< @brief Whether action was given. */ unsigned int mgmkey_given ; /**< @brief Whether mgmkey was given. */ unsigned int new_mgmkey_given ; /**< @brief Whether new-mgmkey was given. */ unsigned int credpwd_given ; /**< @brief Whether credpwd was given. */ unsigned int label_given ; /**< @brief Whether label was given. */ unsigned int reader_given ; /**< @brief Whether reader was given. */ unsigned int touch_given ; /**< @brief Whether touch was given. */ unsigned int context_given ; /**< @brief Whether context was given. */ unsigned int verbose_given ; /**< @brief Whether verbose was given. */ unsigned int derivation_password_given ; /**< @brief Whether derivation-password was given. */ unsigned int enckey_given ; /**< @brief Whether enckey was given. */ unsigned int mackey_given ; /**< @brief Whether mackey was given. */ unsigned int privkey_given ; /**< @brief Whether privkey was given. */ int asymmetric_mode_counter; /**< @brief Counter for mode asymmetric */ int derivation_mode_counter; /**< @brief Counter for mode derivation */ int explicit_mode_counter; /**< @brief Counter for mode explicit */ } ; /** @brief The additional parameters to pass to parser functions */ struct cmdline_parser_params { int override; /**< @brief whether to override possibly already present options (default 0) */ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ int check_required; /**< @brief whether to check that all required options were provided (default 1) */ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ } ; /** @brief the purpose string of the program */ extern const char *gengetopt_args_info_purpose; /** @brief the usage string of the program */ extern const char *gengetopt_args_info_usage; /** @brief the description string of the program */ extern const char *gengetopt_args_info_description; /** @brief all the lines making the help output */ extern const char *gengetopt_args_info_help[]; /** * The command line parser * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info); /** * The command line parser (version with additional parameters - deprecated) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_ext() instead */ int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The command line parser (version with additional parameters) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Save the contents of the option struct into an already open FILE stream. * @param outfile the stream where to dump options * @param args_info the option struct to dump * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info); /** * Save the contents of the option struct into a (text) file. * This file can be read by the config file parser (if generated by gengetopt) * @param filename the file where to save * @param args_info the option struct to save * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info); /** * Print the help */ void cmdline_parser_print_help(void); /** * Print the version */ void cmdline_parser_print_version(void); /** * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ void cmdline_parser_params_init(struct cmdline_parser_params *params); /** * Allocates dynamically a cmdline_parser_params structure and initializes * all its fields to their default values * @return the created and initialized cmdline_parser_params structure */ struct cmdline_parser_params *cmdline_parser_params_create(void); /** * Initializes the passed gengetopt_args_info structure's fields * (also set default values for options that have a default) * @param args_info the structure to initialize */ void cmdline_parser_init (struct gengetopt_args_info *args_info); /** * Deallocates the string fields of the gengetopt_args_info structure * (but does not deallocate the structure itself) * @param args_info the structure to deallocate */ void cmdline_parser_free (struct gengetopt_args_info *args_info); /** * Checks that all the required options were specified * @param args_info the structure to check * @param prog_name the name of the program that will be used to print * possible errors * @return */ int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name); extern const char *cmdline_parser_action_values[]; /**< @brief Possible values for action. */ extern const char *cmdline_parser_touch_values[]; /**< @brief Possible values for touch. */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CMDLINE_H */ yubihsm-shell-2.6.0/yubihsm-auth/README.adoc0000644000175100001770000000304514666527773020106 0ustar runnerdocker== YubiHSM Auth YubiHSM Auth is a command-line tool for the YubiKey HSM Auth application. This is used for storing the authentication keys of a YubiHSM in a YubiKey. === Examples This example shows how to store a new authentication key in the application, then using it with the YubiHSM. First we store the key in a YubiKey, if options are omitted they will be asked for: [source, bash] ---- $ yubihsm-auth -a put --label="default key" --derivation-password="password" --credpwd="my secret" Credential successfully stored ---- Then we authenticate with a YubiHSM (in interactive mode) using the YubiKey: [source, bash] ---- yubihsm> session ykopen 1 "default key" "my secret" trying to connect to reader 'Yubico Yubikey 4 OTP+U2F+CCID 00 00' Created session 0 ---- Alternatively using the command line: [source, bash] ---- $ yubihsm-shell -a get-pseudo-random --ykhsmauth-label="default key" --password="my secret" Session keepalive set up to run every 15 seconds trying to connect to reader 'Yubico Yubikey 4 OTP+U2F+CCID 00 00' Created session 0 06a4d93be9bbcf97891f09979d4297eee335c4ea9526bfb8565baa9239b6359d68d9c636364052bee91a5b1801d6844b88dd3aa1e47f34f2389d841a21398f60ba67507d7f282e8fdc3b7090a2465b3b0358df660f74dd8e9aa5af2c73aadd9d82101c762e558e129703fe44ecb8433537db4d04350141c73ba9d36143afe5264125ec2bfc202d18f73155c34f0e16d45a4ade4a92f17433a6426d4cda6d4b36e831c641be71c561cbeb537e412341b6318810b581b006c29acef3b5bdae157d536d05f4275b86510d6a22c37b352dc148a3400a513dad2a91162795964212b9f361328e5f98fb47ae7ad9e4c4d66ff912d90cb028e15f89d3b8e5d8c3664ed3 ---- yubihsm-shell-2.6.0/yubihsm-auth/version.rc.in0000644000175100001770000000207714666527773020745 0ustar runnerdocker #include #define VER_FILEVERSION @yubihsm_shell_VERSION_MAJOR@,@yubihsm_shell_VERSION_MINOR@,@yubihsm_shell_VERSION_PATCH@,0 #define VER_FILEVERSION_STR "@yubihsm_shell_VERSION_MAJOR@.@yubihsm_shell_VERSION_MINOR@.@yubihsm_shell_VERSION_PATCH@.0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_FILEVERSION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Yubico AB" VALUE "FileDescription", "YubiHSM Auth" VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "yubihsm-auth.exe" VALUE "LegalCopyright", "\xa9 Yubico AB" VALUE "OriginalFilename", "yubihsm-auth.exe" VALUE "ProductName", "YubiHSM" VALUE "ProductVersion", VER_FILEVERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END yubihsm-shell-2.6.0/yubihsm-auth/cmdline.c0000644000175100001770000007215614666530033020070 0ustar runnerdocker/* File autogenerated by gengetopt version 2.23 generated with the following command: gengetopt -i /home/runner/work/yubihsm-shell/yubihsm-shell/yubihsm-auth/cmdline.ggo --output-dir /home/runner/work/yubihsm-shell/yubihsm-shell/yubihsm-auth cmdline The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: we make no copyright claims on it. */ /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifndef FIX_UNUSED #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ #endif #include #include "cmdline.h" const char *gengetopt_args_info_purpose = ""; const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", " -a, --action=ENUM Action to perform (possible\n values=\"calculate\", \"change-mgmkey\",\n \"delete\", \"list\", \"put\", \"reset\",\n \"retries\", \"version\", \"get-challenge\",\n \"get-pubkey\")", " -k, --mgmkey=STRING Management key is required to put and delete\n credentials. Sometimes, this key is also\n referenced as 'Admin Access Code'\n (default=`00000000000000000000000000000000')", " -K, --new-mgmkey=STRING New management key (default=`')", " -p, --credpwd=STRING Credential password is used to access the\n credential when logging into the YubiHSM2.\n Sometimes, this password is also referenced\n as 'User Access Code' (default=`')", " -l, --label=STRING Credential label (default=`')", " -r, --reader=STRING Only use a matching reader (default=`')", " -t, --touch=ENUM Touch required (possible values=\"off\",\n \"on\" default=`off')", " -c, --context=STRING Session keys calculation context (default=`')", " -v, --verbose[=INT] Print more information (default=`0')", "\n Mode: derivation\n Derive keys from a password using PBKDF2", " -d, --derivation-password=STRING\n Derivation password for encryption and MAC keys\n (default=`')", "\n Mode: explicit\n Explicit encryption and MAC keys", " -e, --enckey=STRING Encryption key (default=`')", " -m, --mackey=STRING MAC key (default=`')", "\n Mode: asymmetric\n Explicit ec-p256 private key", " -s, --privkey=STRING Private key (default=`')", 0 }; typedef enum {ARG_NO , ARG_STRING , ARG_INT , ARG_ENUM } cmdline_parser_arg_type; static void clear_given (struct gengetopt_args_info *args_info); static void clear_args (struct gengetopt_args_info *args_info); static int cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error); const char *cmdline_parser_action_values[] = {"calculate", "change-mgmkey", "delete", "list", "put", "reset", "retries", "version", "get-challenge", "get-pubkey", 0}; /*< Possible values for action. */ const char *cmdline_parser_touch_values[] = {"off", "on", 0}; /*< Possible values for touch. */ static char * gengetopt_strdup (const char *s); static void clear_given (struct gengetopt_args_info *args_info) { args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->action_given = 0 ; args_info->mgmkey_given = 0 ; args_info->new_mgmkey_given = 0 ; args_info->credpwd_given = 0 ; args_info->label_given = 0 ; args_info->reader_given = 0 ; args_info->touch_given = 0 ; args_info->context_given = 0 ; args_info->verbose_given = 0 ; args_info->derivation_password_given = 0 ; args_info->enckey_given = 0 ; args_info->mackey_given = 0 ; args_info->privkey_given = 0 ; args_info->asymmetric_mode_counter = 0 ; args_info->derivation_mode_counter = 0 ; args_info->explicit_mode_counter = 0 ; } static void clear_args (struct gengetopt_args_info *args_info) { FIX_UNUSED (args_info); args_info->action_arg = action__NULL; args_info->action_orig = NULL; args_info->mgmkey_arg = gengetopt_strdup ("00000000000000000000000000000000"); args_info->mgmkey_orig = NULL; args_info->new_mgmkey_arg = gengetopt_strdup (""); args_info->new_mgmkey_orig = NULL; args_info->credpwd_arg = gengetopt_strdup (""); args_info->credpwd_orig = NULL; args_info->label_arg = gengetopt_strdup (""); args_info->label_orig = NULL; args_info->reader_arg = gengetopt_strdup (""); args_info->reader_orig = NULL; args_info->touch_arg = touch_arg_off; args_info->touch_orig = NULL; args_info->context_arg = gengetopt_strdup (""); args_info->context_orig = NULL; args_info->verbose_arg = 0; args_info->verbose_orig = NULL; args_info->derivation_password_arg = gengetopt_strdup (""); args_info->derivation_password_orig = NULL; args_info->enckey_arg = gengetopt_strdup (""); args_info->enckey_orig = NULL; args_info->mackey_arg = gengetopt_strdup (""); args_info->mackey_orig = NULL; args_info->privkey_arg = gengetopt_strdup (""); args_info->privkey_orig = NULL; } static void init_args_info(struct gengetopt_args_info *args_info) { args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->action_help = gengetopt_args_info_help[2] ; args_info->mgmkey_help = gengetopt_args_info_help[3] ; args_info->new_mgmkey_help = gengetopt_args_info_help[4] ; args_info->credpwd_help = gengetopt_args_info_help[5] ; args_info->label_help = gengetopt_args_info_help[6] ; args_info->reader_help = gengetopt_args_info_help[7] ; args_info->touch_help = gengetopt_args_info_help[8] ; args_info->context_help = gengetopt_args_info_help[9] ; args_info->verbose_help = gengetopt_args_info_help[10] ; args_info->derivation_password_help = gengetopt_args_info_help[12] ; args_info->enckey_help = gengetopt_args_info_help[14] ; args_info->mackey_help = gengetopt_args_info_help[15] ; args_info->privkey_help = gengetopt_args_info_help[17] ; } void cmdline_parser_print_version (void) { printf ("%s %s\n", (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), CMDLINE_PARSER_VERSION); if (strlen(gengetopt_args_info_versiontext) > 0) printf("\n%s\n", gengetopt_args_info_versiontext); } static void print_help_common(void) { size_t len_purpose = strlen(gengetopt_args_info_purpose); size_t len_usage = strlen(gengetopt_args_info_usage); if (len_usage > 0) { printf("%s\n", gengetopt_args_info_usage); } if (len_purpose > 0) { printf("%s\n", gengetopt_args_info_purpose); } if (len_usage || len_purpose) { printf("\n"); } if (strlen(gengetopt_args_info_description) > 0) { printf("%s\n\n", gengetopt_args_info_description); } } void cmdline_parser_print_help (void) { int i = 0; print_help_common(); while (gengetopt_args_info_help[i]) printf("%s\n", gengetopt_args_info_help[i++]); } void cmdline_parser_init (struct gengetopt_args_info *args_info) { clear_given (args_info); clear_args (args_info); init_args_info (args_info); } void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) { params->override = 0; params->initialize = 1; params->check_required = 1; params->check_ambiguity = 0; params->print_errors = 1; } } struct cmdline_parser_params * cmdline_parser_params_create(void) { struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); cmdline_parser_params_init(params); return params; } static void free_string_field (char **s) { if (*s) { free (*s); *s = 0; } } static void cmdline_parser_release (struct gengetopt_args_info *args_info) { free_string_field (&(args_info->action_orig)); free_string_field (&(args_info->mgmkey_arg)); free_string_field (&(args_info->mgmkey_orig)); free_string_field (&(args_info->new_mgmkey_arg)); free_string_field (&(args_info->new_mgmkey_orig)); free_string_field (&(args_info->credpwd_arg)); free_string_field (&(args_info->credpwd_orig)); free_string_field (&(args_info->label_arg)); free_string_field (&(args_info->label_orig)); free_string_field (&(args_info->reader_arg)); free_string_field (&(args_info->reader_orig)); free_string_field (&(args_info->touch_orig)); free_string_field (&(args_info->context_arg)); free_string_field (&(args_info->context_orig)); free_string_field (&(args_info->verbose_orig)); free_string_field (&(args_info->derivation_password_arg)); free_string_field (&(args_info->derivation_password_orig)); free_string_field (&(args_info->enckey_arg)); free_string_field (&(args_info->enckey_orig)); free_string_field (&(args_info->mackey_arg)); free_string_field (&(args_info->mackey_orig)); free_string_field (&(args_info->privkey_arg)); free_string_field (&(args_info->privkey_orig)); clear_given (args_info); } /** * @param val the value to check * @param values the possible values * @return the index of the matched value: * -1 if no value matched, * -2 if more than one value has matched */ static int check_possible_values(const char *val, const char *values[]) { int i, found, last; size_t len; if (!val) /* otherwise strlen() crashes below */ return -1; /* -1 means no argument for the option */ found = last = 0; for (i = 0, len = strlen(val); values[i]; ++i) { if (strncmp(val, values[i], len) == 0) { ++found; last = i; if (strlen(values[i]) == len) return i; /* exact macth no need to check more */ } } if (found == 1) /* one match: OK */ return last; return (found ? -2 : -1); /* return many values or none matched */ } static void write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) { int found = -1; if (arg) { if (values) { found = check_possible_values(arg, values); } if (found >= 0) fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]); else fprintf(outfile, "%s=\"%s\"\n", opt, arg); } else { fprintf(outfile, "%s\n", opt); } } int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) { int i = 0; if (!outfile) { fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); return EXIT_FAILURE; } if (args_info->help_given) write_into_file(outfile, "help", 0, 0 ); if (args_info->version_given) write_into_file(outfile, "version", 0, 0 ); if (args_info->action_given) write_into_file(outfile, "action", args_info->action_orig, cmdline_parser_action_values); if (args_info->mgmkey_given) write_into_file(outfile, "mgmkey", args_info->mgmkey_orig, 0); if (args_info->new_mgmkey_given) write_into_file(outfile, "new-mgmkey", args_info->new_mgmkey_orig, 0); if (args_info->credpwd_given) write_into_file(outfile, "credpwd", args_info->credpwd_orig, 0); if (args_info->label_given) write_into_file(outfile, "label", args_info->label_orig, 0); if (args_info->reader_given) write_into_file(outfile, "reader", args_info->reader_orig, 0); if (args_info->touch_given) write_into_file(outfile, "touch", args_info->touch_orig, cmdline_parser_touch_values); if (args_info->context_given) write_into_file(outfile, "context", args_info->context_orig, 0); if (args_info->verbose_given) write_into_file(outfile, "verbose", args_info->verbose_orig, 0); if (args_info->derivation_password_given) write_into_file(outfile, "derivation-password", args_info->derivation_password_orig, 0); if (args_info->enckey_given) write_into_file(outfile, "enckey", args_info->enckey_orig, 0); if (args_info->mackey_given) write_into_file(outfile, "mackey", args_info->mackey_orig, 0); if (args_info->privkey_given) write_into_file(outfile, "privkey", args_info->privkey_orig, 0); i = EXIT_SUCCESS; return i; } int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) { FILE *outfile; int i = 0; outfile = fopen(filename, "w"); if (!outfile) { fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } i = cmdline_parser_dump(outfile, args_info); fclose (outfile); return i; } void cmdline_parser_free (struct gengetopt_args_info *args_info) { cmdline_parser_release (args_info); } /** @brief replacement of strdup, which is not standard */ char * gengetopt_strdup (const char *s) { char *result = 0; if (!s) return result; result = (char*)malloc(strlen(s) + 1); if (result == (char*)0) return (char*)0; strcpy(result, s); return result; } int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) { return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); } int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int result; result = cmdline_parser_internal (argc, argv, args_info, params, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { int result; struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) { FIX_UNUSED (args_info); FIX_UNUSED (prog_name); return EXIT_SUCCESS; } static char *package_name = 0; /** * @brief updates an option * @param field the generic pointer to the field to update * @param orig_field the pointer to the orig field * @param field_given the pointer to the number of occurrence of this option * @param prev_given the pointer to the number of occurrence already seen * @param value the argument for this option (if null no arg was specified) * @param possible_values the possible values for this option (if specified) * @param default_value the default value (in case the option only accepts fixed values) * @param arg_type the type of this option * @param check_ambiguity @see cmdline_parser_params.check_ambiguity * @param override @see cmdline_parser_params.override * @param no_free whether to free a possible previous value * @param multiple_option whether this is a multiple option * @param long_opt the corresponding long option * @param short_opt the corresponding short option (or '-' if none) * @param additional_error possible further error specification */ static int update_arg(void *field, char **orig_field, unsigned int *field_given, unsigned int *prev_given, char *value, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, int check_ambiguity, int override, int no_free, int multiple_option, const char *long_opt, char short_opt, const char *additional_error) { char *stop_char = 0; const char *val = value; int found; char **string_field; FIX_UNUSED (field); stop_char = 0; found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0) { if (short_opt != '-') fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (field_given && *field_given && ! override) return 0; if (prev_given) (*prev_given)++; if (field_given) (*field_given)++; if (possible_values) val = possible_values[found]; switch(arg_type) { case ARG_INT: if (val) *((int *)field) = strtol (val, &stop_char, 0); break; case ARG_ENUM: if (val) *((int *)field) = found; break; case ARG_STRING: if (val) { string_field = (char **)field; if (!no_free && *string_field) free (*string_field); /* free previous string */ *string_field = gengetopt_strdup (val); } break; default: break; }; /* check numeric conversion */ switch(arg_type) { case ARG_INT: if (val && !(stop_char && *stop_char == '\0')) { fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val); return 1; /* failure */ } break; default: ; }; /* store the original value */ switch(arg_type) { case ARG_NO: break; default: if (value && orig_field) { if (no_free) { *orig_field = value; } else { if (*orig_field) free (*orig_field); /* free previous string */ *orig_field = gengetopt_strdup (value); } } }; return 0; /* OK */ } static int check_modes( int given1[], const char *options1[], int given2[], const char *options2[]) { int i = 0, j = 0, errors = 0; while (given1[i] >= 0) { if (given1[i]) { while (given2[j] >= 0) { if (given2[j]) { ++errors; fprintf(stderr, "%s: option %s conflicts with option %s\n", package_name, options1[i], options2[j]); } ++j; } } ++i; } return errors; } int cmdline_parser_internal ( int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { int c; /* Character of the parsed option. */ int error_occurred = 0; struct gengetopt_args_info local_args_info; int override; int initialize; int check_required; int check_ambiguity; package_name = argv[0]; /* TODO: Why is this here? It is not used anywhere. */ override = params->override; FIX_UNUSED(override); initialize = params->initialize; check_required = params->check_required; /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); cmdline_parser_init (&local_args_info); optarg = 0; optind = 0; opterr = params->print_errors; optopt = '?'; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "action", 1, NULL, 'a' }, { "mgmkey", 1, NULL, 'k' }, { "new-mgmkey", 1, NULL, 'K' }, { "credpwd", 1, NULL, 'p' }, { "label", 1, NULL, 'l' }, { "reader", 1, NULL, 'r' }, { "touch", 1, NULL, 't' }, { "context", 1, NULL, 'c' }, { "verbose", 2, NULL, 'v' }, { "derivation-password", 1, NULL, 'd' }, { "enckey", 1, NULL, 'e' }, { "mackey", 1, NULL, 'm' }, { "privkey", 1, NULL, 's' }, { 0, 0, 0, 0 } }; c = getopt_long (argc, argv, "hVa:k:K:p:l:r:t:c:v::d:e:m:s:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'a': /* Action to perform. */ if (update_arg( (void *)&(args_info->action_arg), &(args_info->action_orig), &(args_info->action_given), &(local_args_info.action_given), optarg, cmdline_parser_action_values, 0, ARG_ENUM, check_ambiguity, override, 0, 0, "action", 'a', additional_error)) goto failure; break; case 'k': /* Management key is required to put and delete credentials. Sometimes, this key is also referenced as 'Admin Access Code'. */ if (update_arg( (void *)&(args_info->mgmkey_arg), &(args_info->mgmkey_orig), &(args_info->mgmkey_given), &(local_args_info.mgmkey_given), optarg, 0, "00000000000000000000000000000000", ARG_STRING, check_ambiguity, override, 0, 0, "mgmkey", 'k', additional_error)) goto failure; break; case 'K': /* New management key. */ if (update_arg( (void *)&(args_info->new_mgmkey_arg), &(args_info->new_mgmkey_orig), &(args_info->new_mgmkey_given), &(local_args_info.new_mgmkey_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "new-mgmkey", 'K', additional_error)) goto failure; break; case 'p': /* Credential password is used to access the credential when logging into the YubiHSM2. Sometimes, this password is also referenced as 'User Access Code'. */ if (update_arg( (void *)&(args_info->credpwd_arg), &(args_info->credpwd_orig), &(args_info->credpwd_given), &(local_args_info.credpwd_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "credpwd", 'p', additional_error)) goto failure; break; case 'l': /* Credential label. */ if (update_arg( (void *)&(args_info->label_arg), &(args_info->label_orig), &(args_info->label_given), &(local_args_info.label_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "label", 'l', additional_error)) goto failure; break; case 'r': /* Only use a matching reader. */ if (update_arg( (void *)&(args_info->reader_arg), &(args_info->reader_orig), &(args_info->reader_given), &(local_args_info.reader_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "reader", 'r', additional_error)) goto failure; break; case 't': /* Touch required. */ if (update_arg( (void *)&(args_info->touch_arg), &(args_info->touch_orig), &(args_info->touch_given), &(local_args_info.touch_given), optarg, cmdline_parser_touch_values, "off", ARG_ENUM, check_ambiguity, override, 0, 0, "touch", 't', additional_error)) goto failure; break; case 'c': /* Session keys calculation context. */ if (update_arg( (void *)&(args_info->context_arg), &(args_info->context_orig), &(args_info->context_given), &(local_args_info.context_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "context", 'c', additional_error)) goto failure; break; case 'v': /* Print more information. */ if (update_arg( (void *)&(args_info->verbose_arg), &(args_info->verbose_orig), &(args_info->verbose_given), &(local_args_info.verbose_given), optarg, 0, "0", ARG_INT, check_ambiguity, override, 0, 0, "verbose", 'v', additional_error)) goto failure; break; case 'd': /* Derivation password for encryption and MAC keys. */ args_info->derivation_mode_counter += 1; if (update_arg( (void *)&(args_info->derivation_password_arg), &(args_info->derivation_password_orig), &(args_info->derivation_password_given), &(local_args_info.derivation_password_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "derivation-password", 'd', additional_error)) goto failure; break; case 'e': /* Encryption key. */ args_info->explicit_mode_counter += 1; if (update_arg( (void *)&(args_info->enckey_arg), &(args_info->enckey_orig), &(args_info->enckey_given), &(local_args_info.enckey_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "enckey", 'e', additional_error)) goto failure; break; case 'm': /* MAC key. */ args_info->explicit_mode_counter += 1; if (update_arg( (void *)&(args_info->mackey_arg), &(args_info->mackey_orig), &(args_info->mackey_given), &(local_args_info.mackey_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "mackey", 'm', additional_error)) goto failure; break; case 's': /* Private key. */ args_info->asymmetric_mode_counter += 1; if (update_arg( (void *)&(args_info->privkey_arg), &(args_info->privkey_orig), &(args_info->privkey_given), &(local_args_info.privkey_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "privkey", 's', additional_error)) goto failure; break; case 0: /* Long option with no short option */ case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ } /* while */ if (args_info->asymmetric_mode_counter && args_info->derivation_mode_counter) { int asymmetric_given[] = {args_info->privkey_given, -1}; const char *asymmetric_desc[] = {"--privkey", 0}; int derivation_given[] = {args_info->derivation_password_given, -1}; const char *derivation_desc[] = {"--derivation-password", 0}; error_occurred += check_modes(asymmetric_given, asymmetric_desc, derivation_given, derivation_desc); } if (args_info->asymmetric_mode_counter && args_info->explicit_mode_counter) { int asymmetric_given[] = {args_info->privkey_given, -1}; const char *asymmetric_desc[] = {"--privkey", 0}; int explicit_given[] = {args_info->enckey_given, args_info->mackey_given, -1}; const char *explicit_desc[] = {"--enckey", "--mackey", 0}; error_occurred += check_modes(asymmetric_given, asymmetric_desc, explicit_given, explicit_desc); } if (args_info->derivation_mode_counter && args_info->explicit_mode_counter) { int derivation_given[] = {args_info->derivation_password_given, -1}; const char *derivation_desc[] = {"--derivation-password", 0}; int explicit_given[] = {args_info->enckey_given, args_info->mackey_given, -1}; const char *explicit_desc[] = {"--enckey", "--mackey", 0}; error_occurred += check_modes(derivation_given, derivation_desc, explicit_given, explicit_desc); } FIX_UNUSED(check_required); cmdline_parser_release (&local_args_info); if ( error_occurred ) return (EXIT_FAILURE); return 0; failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ yubihsm-shell-2.6.0/doc/0000755000175100001770000000000014666527773014445 5ustar runnerdockeryubihsm-shell-2.6.0/doc/API_Changes.adoc0000644000175100001770000003263414666527773017346 0ustar runnerdocker== 1.0.4 -> 2.0.0 === Definitions ==== Return Codes [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`YHR_MEMORY` | `YHR_MEMORY_ERROR` | `-1` |`YHR_NET_ERROR` | `YHR_CONNECTION_ERROR` | `-3` |`YHR_INVALID_PARAMS` | `YHR_INVALID_PARAMETERS` | `-5` |`YHR_AUTH_SESSION_ERROR` | `YHR_SESSION_AUTHENTICATION_FAILED` | `-9` |`YHR_DEVICE_INV_COMMAND` | `YHR_DEVICE_INVALID_COMMAND` | `-12` |`YHR_DEVICE_INV_DATA` | `YHR_DEVICE_INVALID_DATA` | `-13` |`YHR_DEVICE_INV_SESSION` | `YHR_DEVICE_INVALID_SESSION` | `-14` |`YHR_DEVICE_AUTH_FAIL` | `YHR_DEVICE_AUTHENTICATION_FAILED` | `-15` |`YHR_DEVICE_INV_PERMISSION` | `YHR_DEVICE_INSUFFICIENT_PERMISSIONS` | `-20` |`YHR_DEVICE_OBJ_NOT_FOUND` | `YHR_DEVICE_OBJECT_NOT_FOUND` | `-22` |`YHR_DEVICE_ID_ILLEGAL` | `YHR_DEVICE_INVALID_ID` | `-23` |`YHR_DEVICE_CMD_UNEXECUTED` | `YHR_DEVICE_COMMAND_UNEXECUTED` | `-26` | - | `YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION` | `-30` |======================= ==== Object Types [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`YH_AUTHKEY` | `YH_AUTHENTICATION_KEY` | `0x02` |`YH_ASYMMETRIC` | `YH_ASYMMETRIC_KEY` | `0x03` |`YH_WRAPKEY` | `YH_WRAP_KEY` | `0x04` |`YH_HMACKEY` | `YH_HMAC_KEY` | `0x05` |`YH_PUBLIC` | `YH_PUBLIC_KEY` | `0x83` |======================= ==== Algorithms [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`YH_ALGO_OPAQUE_X509_CERT` | `YH_ALGO_OPAQUE_X509_CERTIFICATE` | `31` |`YH_ALGO_TEMPL_SSH` | `YH_ALGO_TEMPLATE_SSH` | `36` |`YH_ALGO_YUBICO_OTP_AES128` | `YH_ALGO_AES128_YUBICO_OTP` | `37` |`YH_ALGO_YUBICO_AES_AUTH` | `YH_ALGO_AES128_YUBICO_AUTHENTICATION` | `38` |`YH_ALGO_YUBICO_OTP_AES192` | `YH_ALGO_AES192_YUBICO_OTP` | `39` |`YH_ALGO_YUBICO_OTP_AES256` | `YH_ALGO_AES256_YUBICO_OTP` | `40` |======================= ==== Commands [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`YHC_CREATE_SES` | `YHC_CREATE_SESSION` | `0x03` |`YHC_AUTH_SES` | `YHC_AUTHENTICATE_SESSION` | `0x04` |`YHC_SES_MSG` | `YHC_SESSION_MESSAGE` | `0x05` |`YHC_RESET` | `YHC_RESET_DEVICE` | `0x08` |`YHC_CLOSE_SES` | `YHC_CLOSE_SESSION` | `0x40` |`YHC_STATS` | `YHC_GET_STORAGE_INFO` | `0x41` |`YHC_PUT_AUTHKEY` | `YHC_PUT_AUTHENTICATION_KEY` | `0x44` |`YHC_GEN_ASYMMETRIC_KEY` | `YHC_GENERATE_ASYMMETRIC_KEY` | `0x46` |`YHC_SIGN_DATA_PKCS1` | `YHC_SIGN_PKCS1` | `0x47` |`YHC_LIST` | `YHC_LIST_OBJECTS` | `0x48` |`YHC_GET_LOGS` | `YHC_GET_LOG_ENTRIES` | `0x4d` |`YHC_PUT_OPTION` | `YHC_SET_OPTION` | `0x4f` |`YHC_HMAC_DATA` | `YHC_SIGN_HMAC` | `0x53` |`YHC_GET_PUBKEY` | `YHC_GET_PUBLIC_KEY` | `0x54` |`YHC_SIGN_DATA_PSS` | `YHC_SIGN_PSS` | `0x55` |`YHC_SIGN_DATA_ECDSA` | `YHC_SIGN_ECDSA` | `0x56` |`YHC_DECRYPT_ECDH` | `YHC_DERIVE_ECDH` | `0x57` |`YHC_SSH_CERTIFY` | `YHC_SIGN_SSH_CERTIFICATE` | `0x5d` |`YHC_OTP_DECRYPT` | `YHC_DECRYPT_OTP` | `0x60` |`YHC_OTP_AEAD_CREATE` | `YHC_CREATE_OTP_AEAD` | `0x61` |`YHC_OTP_AEAD_RANDOM` | `YHC_RANDOMIZE_OTP_AEAD` | `0x62` |`YHC_OTP_AEAD_REWRAP` | `YHC_REWRAP_OTP_AEAD` | `0x63` |`YHC_ATTEST_ASYMMETRIC` | `YHC_SIGN_ATTESTATION_CERTIFICATE` | `0x64` |`YHC_SIGN_DATA_EDDSA` | `YHC_SIGN_EDDSA` | `0x6a` |`YHC_BLINK` | `YHC_BLINK_DEVICE` | `0x6b` | - | `YHC_CHANGE_AUTHENTICATION_KEY` | `0x6c` |======================= === Object Types [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`authkey` | `authentication-key` | `0x02 |`asymmetric` | `asymmetric-key` | `0x03 |`hmackey` | `hmac-key` | `0x05 |`otpaeadkey` | `otp-aead-key` | `0x07 |`wrapkey` | `wrap-key` | `0x04` |======================= === Capabilities [options="header"] |======================= |1.0.4 | 2.0.0 | Hex value |`asymmetric_decrypt_ecdh` | `derive-ecdh` | `0x0b` |`asymmetric_decrypt_oaep` | `decrypt-oaep` | `0x0a` |`asymmetric_decrypt_pkcs` | `decrypt-pkcs` | `0x09` |`asymmetric_gen` | `generate-asymmetric-key` | `0x04` |`asymmetric_sign_ecdsa` | `sign-ecdsa` | `0x07` |`asymmetric_sign_eddsa` | `sign-eddsa` | `0x08` |`asymmetric_sign_pkcs` | `sign-pkcs` | `0x05` |`asymmetric_sign_pss` | `sign-pss` | `0x06` |`attest` | `sign-attestation-certificate` | `0x22` |`audit` | `get-log-entries` | `0x18` |`export_ under_wrap` | `exportable-under-wrap` | `0x10` |`export_wrapped` | `export-wrapped` | `0x0c` |`delete_asymmetric` | `delete-asymmetric-key` | `0x29` |`delete_authkey` | `delete-authentication-key` | `0x28` |`delete_hmackey` | `delete-hmac-key` | `0x2b` |`delete_opaque` | `delete-opaque` | `0x27` |`delete_otp_aead_key` | `delete-otp-aead-key` | `0x2d` |`delete_template` | `delete-template` | `0x2c` |`delete_wrapkey` | `delete-wrap-key` | `0x2a` |`generate_otp_aead_key` | `generate-otp-aead-key` | `0x24` |`generate_wrapkey` | `generate-wrap-key` | `0x0f` |`get_opaque` | `get-opaque` | `0x00` |`get_option` | `get-option` | `0x12` |`get_randomness` | `get-pseudo-random` | `0x13` |`get_template` | `get-template` | `0x1a` |`hmackey_generate` | `generate-hmac-key` | `0x15` |`hmac_data` | `sign-hmac` | `0x16` |`hmac_verify` | `verify-hmac` | `0x17` |`import_wrapped` | `import-wrapped` | `0x0d` |`otp_aead_create` | `create-otp-aead` | `0x1e` |`otp_aead_random` | `randomize-otp-aead` | `0x1f` |`otp_aead_rewrap_from` | `rewrap-from-otp-aead-key` | `0x20` |`otp_aead_rewrap_to` | `rewrap-to-otp-aead-key` | `0x21` |`otp_decrypt` | `decrypt-otp` | `0x1d` |`put_asymmetric` | `put-asymmetric-key` | `0x03` |`put_authkey` | `put-authentication-key` | `0x02` |`put_hmackey` | `put-mac-key` | `0x14` |`put_opaque` | `put-opaque` | `0x01` |`put_option` | `set-option` | `0x11` |`put_otp_aead_key` | `put-otp-aead-key` | `0x23` |`put_template` | `put-template` | `0x1b` |`put_wrapkey` | `put-wrap-key` | `0x0e` |`reset` | `reset-device` | `0x1c` |`ssh_certify` | `sign-ssh-certificate` | `0x19` |`unwrap_data` | `unwrap-data` | `0x26` |`wrap_data` | `wrap-data` | `0x25` | - | `change-authentication-key` | `0x2e` |======================= === Algorithms [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`yubico-aes-auth` | `aes128-yubico-authentication` | `38` |`yubico-otp-aes128` | `aes128-yubico-otp` | `37` |`yubico-otp-aes192` | `aes192-yubico-otp` | `39` |`yubico-otp-aes256` | `aes256-yubico-otp` | `40` |`opaque` | `opaque-data` | `30` |`x509-cert` | `opaque-x509-certificate` | `31` |======================= === Device Options [options="header"] |======================= |1.0.4 | 2.0.0 | Numeric value |`command_audit` | `command-audit` | `3` |`force_audit` | `force-audit` | `1` |======================= === Function Calls [options="header"] |======================= |1.0.4 | 2.0.0 |`yh_rc yh_set_verbosity(uint8_t verbosity)` | `yh_rc yh_set_verbosity(yh_connector *connector, uint8_t verbosity)` |`void yh_set_debug_output(FILE *output)` | `void yh_set_debug_output(yh_connector *connector, FILE *output)` |`yh_rc yh_connect_all(yh_connector **connectors, size_t *n_connectors, int timeout), yh_rc yh_connect_best(yh_connector **connectors, size_t n_connectors, int *idx` | `yh_rc yh_connect(yh_connector *connector, int timeout)` |`yh_rc yh_create_session_derived(yh_connector *connector, uint16_t auth_keyset_id, const uint8_t *password, size_t password_len, bool recreate_session, uint8_t *context, size_t context_len, yh_session **session)` | `yh_rc yh_create_session_derived(yh_connector *connector, uint16_t authkey_id, const uint8_t *password, size_t password_len, bool recreate_session, yh_session **session)` |`yh_rc yh_create_session(yh_connector *connector, uint16_t auth_keyset_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate_session, uint8_t *context, size_t context_len, yh_session **session)` | `yh_rc yh_create_session(yh_connector *connector, uint16_t authkey_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len, bool recreate_session, yh_session **session)` |`yh_rc yh_begin_create_session_ext(yh_connector *connector, uint16_t auth_keyset_id, uint8_t *context, size_t context_len, uint8_t *card_cryptogram, size_t card_cryptogram_len, yh_session **session)` | `yh_rc yh_begin_create_session_ext(yh_connector *connector, uint16_t authkey_id, uint8_t **context, uint8_t *card_cryptogram, size_t card_cryptogram_len, yh_session **session)` |`yh_rc yh_finish_create_session_ext(yh_connector *connector, yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *context, size_t context_len, uint8_t *card_cryptogram, size_t card_cryptogram_len)` | `yh_rc yh_finish_create_session_ext(yh_connector *connector, yh_session *session, const uint8_t *key_senc, size_t key_senc_len, const uint8_t *key_smac, size_t key_smac_len, const uint8_t *key_srmac, size_t key_srmac_len, uint8_t *card_cryptogram, size_t card_cryptogram_len)` |`yh_rc yh_authenticate_session(yh_session *session, uint8_t *context, size_t context_len)` | `yh_rc yh_authenticate_session(yh_session *session)` |`yh_rc yh_util_get_pubkey()` | `yh_rc yh_util_get_public_key()` |`yh_rc yh_util_hmac()` | `yh_rc yh_util_sign_hmac()` |`yh_rc yh_util_get_random()` | `yh_rc yh_util_get_pseudo_random()` |`yh_rc yh_util_import_key_rsa()` | `yh_rc yh_util_import_rsa_key()` |`yh_rc yh_util_import_key_ec()` | `yh_rc yh_util_import_ec_key()` |`yh_rc yh_util_import_key_ed()` | `yh_rc yh_util_import_ed_key()` |`yh_rc yh_util_import_key_hmac()` | `yh_rc yh_util_import_hmac_key()` |`yh_rc yh_util_generate_key_rsa()` | `yh_rc yh_util_generate_rsa_key()` |`yh_rc yh_util_generate_key_ec()` | `yh_rc yh_util_generate_ec_key()` |`yh_rc yh_util_generate_key_ed()` | `yh_rc yh_util_generate_ed_key()` |`yh_rc yh_util_hmac_verify()` | `yh_rc yh_util_verify_hmac()` |`yh_rc yh_util_generate_key_hmac()` | `yh_rc yh_util_generate_hmac_key()` |`yh_rc yh_util_decrypt_ecdh()` | `yh_rc yh_util_derive_ecdh()` |`yh_rc yh_util_import_key_wrap()` | `yh_rc yh_util_import_wrap_key()` |`yh_rc yh_util_generate_key_wrap()` | `yh_rc yh_util_generate_wrap_key()` |`yh_rc yh_util_get_logs()` | `yh_rc yh_util_get_log_entries()` |`yh_rc yh_util_ssh_certify()` | `yh_rc yh_util_sign_ssh_certificate()` |`yh_rc yh_util_import_authkey()` | `yh_rc yh_util_import_authentication_key_derived()` | - | `yh_rc yh_util_import_authentication_key(yh_session *session, uint16_t *key_id, const char *label, uint16_t domains, const yh_capabilities *capabilities, const yh_capabilities *delegated_capabilities, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)` | - | `yh_rc yh_util_change_authentication_key(yh_session *session, uint16_t *key_id, const uint8_t *key_enc, size_t key_enc_len, const uint8_t *key_mac, size_t key_mac_len)` | - | `yh_rc yh_util_change_authentication_key_derived(yh_session *session, uint16_t *key_id, const uint8_t *password, size_t password_len)` |`yh_rc yh_util_otp_aead_create()` | `yh_rc yh_util_create_otp_aead()` |`yh_rc yh_util_otp_aead_random()` | `yh_rc yh_util_randomize_otp_aead()` |`yh_rc yh_util_otp_decrypt()` | `yh_rc yh_util_decrypt_otp()` |`yh_rc yh_util_put_otp_aead_key()` | `yh_rc yh_util_import_otp_aead_key()` |`yh_rc yh_util_attest_asymmetric()` | `yh_rc yh_util_sign_attestation_certificate()` |`yh_rc yh_util_put_option()` | `yh_rc yh_util_set_option()` |`yh_rc yh_util_get_storage_stats()` | `yh_rc yh_util_get_storage_info()` |`yh_rc yh_util_blink()` | `yh_rc yh_util_blink_device()` |`yh_rc yh_util_reset()` | `yh_rc yh_util_reset_device()` |`yh_rc yh_capabilities_to_num()` | `yh_rc yh_string_to_capabilities()` |`yh_rc yh_num_to_capabilities()` | `yh_rc yh_capabilities_to_strings()` |`yh_rc yh_parse_domains()` | `yh_rc yh_string_to_domains()` |======================= yubihsm-shell-2.6.0/CHANGELOG0000644000175100001770000003012314666527773015111 0ustar runnerdocker=== Version 2.6.0 lib: shell: pkcs11: Add support for asymmetric wrap pkcs11: Add support for PKCS11 3.0 cmd: Fix opening a session using credentials stored on a YubiKey build: Always compile with YubiHSM Auth enabled === Version 2.5.0 pkcs11: Add support for applying KDF after ECDH derivation pkcs11: Shell: Fix minor bugs test: Increase test coverage === Version 2.4.2 pkcs11: Add Symmetric key capabilities to searchable criteria pkcs11: Add support for CKA_KEY_TYPE when searching for objects pkcs11: Add support for CKA_MODIFIABLE and CKA_COPYABLE attributes for AES and Wrap keys test: Increase test coverage === Version 2.4.1 pkcs11: Security update for https://www.yubico.com/support/security-advisories/ysa-2023-01/[YSA-2023-01] pkcs11: Allow only a user with access to all the object's domains to edit its attributes pkcs11: Allow for the creation of an asymmetric key even if CKA_ID or CKA_LABEL attribute values for the private and public key are different. pkcs11: Improve backup capabilities of objects whose attributes have been changed pkcs11: Add support for CKA_ALLOWED_MECHANISMS pkcs11: Fix CKA_SENSITIVE and CKA_PRIVATE return value for opaque objects pkcs11: Add support for CKA_EXTRACTABLE for imported certificates pkcs11: Fix regression that only allowed encryption with private keys lib: pkcs11: Delay client side MAC check to avoid leaving unauthenticated sessions open shell: Fix handling of ED25519 keys build: Update release script for Centos7 build: Fix paths in pkg-config template build: Set linker flags by platform test: Improve test coverage === Version 2.4.0 lib: shell: pkcs11: Add support for symmetric encryption, AES-ECB and AES-CBC (Requires firmware version 2.3 and later) shell: Enable asymmetric authentication by default (Requires firmware version 2.3 and later) shell: Allow hex format when creating symmetric authentication key shell: Improve usage of the list command shell: Allow yubihsm-auth reader to be specified shell: Enable backend TLS support in the command line pkcs11: Add support for modifying CKA_ID and CKA_LABEL attribute values pkcs11: Improve handling of attributes pkcs11: Improve debug output pkcs11: Improve error handling pkcs11: Change in firmware/harware version representation. The version as reported by C_GetSlotInfo and C_GetTokenInfo will now show minor*10+patch, instead of minor*100+patch build: Dependecy updates === Version 2.3.2 shell: Remove limit on input file size shell: pkcs11: build: Minor improvements === Version 2.3.1 lib: Fix handling errors received from the YubiHSM shell: Enforce valid DER certificate when importing a certificate shell: Support PEM in-format when importing a certificate shell: pkcs11: Fix minor memory leaks pkcs11: Better handling of invalid input build: Better build experience on MacOS build: Better usage of security flags build: Improve scripts to build debian packages test: Improve testing === Version 2.3.0a build: Enable additional hardening flags when building with CMake < 3.14 === Version 2.3.0 lib: Security update for https://www.yubico.com/support/security-advisories/ysa-2021-04/[YSA-2021-04] lib: Improve backend loading on Windows lib: Add support for ecdh primitives using bcrypt on Windows lib: cli: Improve error handling lib: pkcs11: Add more connection option lib: pkcs11: cli: Fix minor bugs cli: Rename set-option to put-option and add support for get-option pkcs11: Add support for RSA encryption yubihsm-auth: No PSCS reader name filtering by default build: Add version details to yubihsm_pkcs11 module and libykhsmauth library files on Windows build: Make minimum CMake version required 3.5 test: Improved testing === Version 2.2.0 shell: Enable ykhsmauth to be used from commandline ykhsmauth: lib: Add support for YubiCrypt authentication yubihsm-auth: Add CLI for YubiCrypt authentication === Version 2.1.0 lib: Security update for https://www.yubico.com/support/security-advisories/ysa-2021-01/[YSA-2021-01] lib: Add FIPS-mode option lib: Add support for rsa-pkcs1-decrypt algorithm lib: shell: Add support for OTP AEAD rewrap shell: Add support writing attestation certificate to a file pkcs11: Add support for CKA_TRUSTED attribute all: Fix potential memory leaks all: Improve error handling doc: Clarify the minimum length of the password used with PKCS11 === Version 2.0.3 all: Move away from archaic offensive terms all: Update build scripts to account for changes in newer MACOS all: Build on Windows with Visual Studio 2019 pkcs11: Enable .Net to load yubihsm-pkcs11.dylib lib: Fix memory leaks lib: Security fixes lib: Add a session identifier for the backend lib: Make the backend more thread-safe on Windows shell: Honor the base64 format when returning a public key shell: Honor the PEM format when returning a certificate shell: Improve parsing of command line arguments when using OAEP decryption shell: Add support for special (national) characters test: Improve testing === Version 2.0.2 yhauth: Report touch policy as part of the "list" command ykyh: Allow reading the password from stdin yhwrap: Fix wrapping of ED25519 keys shell: Fix ED25519 public key PEM formatting shell: Replace unprintable characters in the object label with '.' ci: Fail early if DEFAULT_CONNECTOR_URL is not set ci: Update homebrew dependencies build: Add two bionic-based builds build: Fix 32-bit Windows builds with mingw32/gcc7 build: Ensure that PCSC is not automatically used on Windows tool: Stop the timer for keepalive functionality while reading the password string misc: Allow disabling link time optimization. misc: Fixes and improvements to build, work and test on FreeBSD. === Version 2.0.1 shell: Add "blink-device" command in CLI mode shell: Add "set-log-index" command to CLI mode shell: Add "exit" as an alias to the "quit" command. shell: Add an optional output file to "audit get" command shell: No openning a session for commands that do not need one shell/yhwrap/pkcs11: open all files in binary mode to keep Windows from changing line ends shell: Install the sigalarm handler in CLI mode build: Add support for installing to lib64 on Fedora build: Only use LTO on clang > 7 build: Add a library only build option examples: Improve code examples test: Tests are improved and are better adapted for MacOS pkcs11/tests: Only run ecdh engine tests on openssl 1.1+ lib: Improve handling of device memory lib: Allow both USB and HTTP support to be compiled in static library lib: Implement signing using sign-eddsa lib: Add the possibility to generate authkey specifying all the capabilities in their string form lib/curl: Include the curl strerror in debug when a connection fails doc: Improvement in documentation, README files and command help === Version 2.0.0 lib: Fix issue with session creation if the authentication key ID is too high lib: Fix a potential issue with memory operations lib: Fix a potential issue with data left after previous transactions or connections lib: Better documentation of arguments lib: Better handling of errors lib: Rename object types, algorithms, capabilities, commands, command options and errors lib: API improvements lib: Add a feature to derive an authentication key from a password lib: Add a feature to change an authentication key pkcs11: Added support for C_DeriveKey() shell: More efficient use of the keepalive function shell: More efficient handling of sessions when a connection is terminated shell: Change keepalive command to a toggle (on/off) tests: Make code examples compile tests: Add support for running tests using direct USB connection all: Drop unused files all: Re-organization of file structure doc: Drop documentation from the code base and moved the content to Yubico's developers website (https://developers.yubico.com/YubiHSM2/) === Version 1.0.4 pkcs11: Fix a potential issue with RSA bit calculation in C_GetMechanismInfo() pkcs11: Fix a case where we return the wrong error from C_GetMechanismList() pkcs11: Add a way for users to pass in options over the API to C_Initialize() connector: Fix a race condition when the usb state was re-created. connector: Better error reporting in some failure cases. connector: Fix issues where the connector could hang on Windows. connector: Fix an issue where the connector would not reconnect on Windows. shell: Fix an issue with importing HMAC keys. === Version 1.0.3 shell: Handle return values from reset correctly on windows. connector: Return HTTP errors when operations fail. lib: Handle HTTP errors correctly on windows. lib: Fix printing of time in debug on windows. pkcs11: Fix a problem in C_FindObjects() where not all items would be returned === Version 1.0.2 lib: Fix connect timeout on windows lib: Fix debugging to file lib/pkcs11/shell: Openssl 1.1 compatibility lib: Mark internal symbols as hidden correctly pkcs11: Fix an error case leaving the session in a broken state pkcs11: Start session IDs from 1, not 0 pkcs11: Add option to set connect timeout pkcs11: Accept C_SetAttributeValue() for CKA_ID and CKA_LABEL if unchanged setup: Fix broken debian package shell: Implement decrypt-ecdh in non-interactive mode connector: On Windows use internal USB libraries instead of libusb connector: Implement Host header allow listing (Use to prevent DNS rebinding attacks in applicable environments, e.g., if there is an absolute need to use a web browser on the host where the Yubihsm2 is installed to connect to untrusted web sites on the Internet. This is not a recommended practice.) === Version 1.0.1 shell: Fix hashing so signing from windows shell works shell: Sorted output pkcs11: Handle ecdsa with longer hash than key pkcs11: Correct error for trying to extract EC key pkcs11: Fix native locking on windows pkcs11: Correct linking on macos lib: Fix logic in session re-use lib: Mark all internal symbols as hidden ksp: Handle passwords longer than 8 characters all: Provide deb packages on debian/ubuntu === Version 0.2.1 doc: add Compatibility.adoc doc: fixup GET LOGS text doc: fixup GET LOGS stanza doc: fixup GET OBJECT INFO text doc: add text about pkcs11 configuration examples/attest: add reading out of cert after loading it examples/import_rsa: change import_rsa example to use pss signing examples: add wrap_data example examples: change all examples to use yh_parse_domains lib/tool/doc: add blink command log: add yh_set_connector_option for transport options lib: give create_session functions a reopen option lib: add OBJECT_EXISTS error lib: allow yh_util_get_object_info to not fill in an object lib: implement yh_util_reset lib: new function for setting debug output: yh_set_debug_output pkcs11: add CKA_ENCRYPT and CKA_VERIFY to public keys pkcs11: add an offset to the vendor defined values pkcs11: add checks for boolean attributes we just accept pkcs11: add configfile options for setting verbosity pkcs11: add debug output file to pkcs11 config pkcs11: don't set CKF_DECRYPT for pkcs+hash mechanisms pkcs11: fix verify for CKM_RSA_PKCS_PSS pkcs11: fixup for C_FindObjectsInit being called without logging in pkcs11: fixup session release in C_CloseSession pkcs11: ignore CKA_APPLICATION in object filtering pkcs11: ignore CKA_KEY_TYPE in C_FindObjectsInit pkcs11: in C_FindObjectsInit make more initial state earlier pkcs11: in C_FindObjectsInit set operation type as late as possible pkcs11: in C_GetSlotList detect overflow more reliably pkcs11: move CKA_ENCRYPT and CKA_VERIFY from hard true on pubkey pkcs11: move CKA_VERIFY and CKA_ENCRYPT from hard true for ec pubkey pkcs11: move wrap/unwrap on rsa generate to unchecked pkcs11: never try to delete a public key, lie and say it's fine instead pkcs11: print more debug info on OAEP mechanism error pkcs11: remove some skipped pkcs11test tests, we fail them correctly pkcs11: return CKR_ATTRIBUTE_SENSITIVE on CKA_PRIVATE_EXPONENT pkcs11: truncate CKA_ID to two bytes if it's longer pkcs11: when closing the debug output file, reset it to stderr tool: drop local connector spawn code tool: add decrypt ecdh command tool: add decrypt oaep command tool: add output for decrypt pkcs1v15 tool: cleanup created objects after benchmark tool: fixup otp decrypt that has to hex decode the otp tool: for ecdh benchmarks delete the temporary key tool: print a message when doing benchmark setup tool: make the reset command print nicer messages yhwrap: add hmac key pre-split yubihsm-shell-2.6.0/src/0000755000175100001770000000000014666530034014447 5ustar runnerdockeryubihsm-shell-2.6.0/src/CMakeLists.txt0000644000175100001770000000573614666527773017242 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() set ( SOURCE commands.c main.c ../common/util.c ../common/hash.c ../common/parsing.c ../common/openssl-compat.c ) if(WIN32) set(SOURCE ${SOURCE} cmdline.c) include(${CMAKE_SOURCE_DIR}/cmake/getopt.cmake) find_getopt() else(WIN32) include(gengetopt) find_gengetopt () add_gengetopt_files (cmdline "--conf-parser") set(SOURCE ${SOURCE} ${GGO_C}) endif(WIN32) include_directories ( ${LIBCRYPTO_INCLUDEDIR} ${LIBEDIT_INCLUDEDIR} ${CMAKE_CURRENT_SOURCE_DIR}/../lib ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../common ) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../ykhsmauth) set(YKHSMAUTH_LIB ykhsmauth) set(YKHSMAUTH_LIB_STATIC ykhsmauth_static) if(WIN32) list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) endif(WIN32) # NOTE(adma): required by gengetopt add_definitions (-DPACKAGE="yubihsm-shell") add_definitions (-DVERSION="${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") list(APPEND LCOV_REMOVE_PATTERNS "'${PROJECT_SOURCE_DIR}/src/cmdline.c'") add_executable (yubihsm-shell ${SOURCE}) if (ENABLE_STATIC) add_executable (yubihsm-shell_static ${SOURCE}) set_target_properties (yubihsm-shell_static PROPERTIES COMPILE_FLAGS "-DSTATIC") target_link_libraries(yubihsm-shell_static ${LIBCRYPTO_LDFLAGS} ${LIBEDIT_LDFLAGS} ${GETOPT_LIBS} yubihsm_static ${YKHSMAUTH_LIB_STATIC}) add_coverage (yubihsm-shell_static) endif () target_link_libraries ( yubihsm-shell ${LIBCRYPTO_LDFLAGS} ${LIBEDIT_LDFLAGS} ${GETOPT_LIBS} yubihsm ${YKHSMAUTH_LIB}) # Set install RPATH set_target_properties(yubihsm-shell PROPERTIES INSTALL_RPATH "${YUBIHSM_INSTALL_LIB_DIR}") add_coverage (yubihsm-shell) install( TARGETS yubihsm-shell ARCHIVE DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" RUNTIME DESTINATION "${YUBIHSM_INSTALL_BIN_DIR}") if (NOT WITHOUT_MANPAGES) include (help2man) add_help2man_manpage (yubihsm-shell.1 yubihsm-shell) add_custom_target (yubihsm-shell-man ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/yubihsm-shell.1 ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/yubihsm-shell.1" DESTINATION "${YUBIHSM_INSTALL_MAN_DIR}/man1") endif() add_subdirectory (tests) yubihsm-shell-2.6.0/src/yubihsm-shell.h0000644000175100001770000000317714666527773017435 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YUBIHSM_SHELL_H #define YUBIHSM_SHELL_H #include #include #include #include #define UNUSED(x) (void) (x) typedef enum { fmt_nofmt, fmt_base64, fmt_binary, fmt_hex, fmt_PEM, fmt_password, fmt_ASCII } cmd_format; static const struct { const char *name; cmd_format format; } formats[] = { {"default", fmt_nofmt}, {"base64", fmt_base64}, {"binary", fmt_binary}, {"hex", fmt_hex}, {"PEM", fmt_PEM}, {"password", fmt_password}, {"ASCII", fmt_ASCII}, }; typedef struct { uint8_t **device_pubkey_list; char **connector_list; yh_connector *connector; yh_session *sessions[256]; ykhsmauth_state *state; FILE *out; char *cacert; char *cert; char *key; char *proxy; char *noproxy; } yubihsm_context; int actions_run(struct gengetopt_args_info *args_info); int do_put_key(uint8_t *enc_key, uint8_t *mac_key, uint16_t key_id, uint16_t domains, uint32_t capabilities, yh_session *ses); #ifdef _MSC_VER #pragma strict_gs_check(on) #endif #endif yubihsm-shell-2.6.0/src/tests/0000755000175100001770000000000014666527773015631 5ustar runnerdockeryubihsm-shell-2.6.0/src/tests/CMakeLists.txt0000644000175100001770000000200514666527773020366 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # find_program (BASH_PROGRAM bash) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/data.txt ${CMAKE_CURRENT_BINARY_DIR}/data.txt COPYONLY) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/sig.out ${CMAKE_CURRENT_BINARY_DIR}/sig.out COPYONLY) add_test( NAME bash_tests COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/tests.sh ) add_test( NAME wrapped_tests COMMAND ${BASH_PROGRAM} ${CMAKE_CURRENT_SOURCE_DIR}/wrapped_tests.sh ) yubihsm-shell-2.6.0/src/tests/sig.out0000644000175100001770000000000014666527773017132 0ustar runnerdockeryubihsm-shell-2.6.0/src/tests/tests.sh0000755000175100001770000000612114666527773017332 0ustar runnerdocker#!/bin/bash # # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # set -e set -x TMPDIR=$(mktemp -d) #trap 'rm -rf "$TMPDIR"' INT TERM EXIT DATA="$TMPDIR/data" SIG="$TMPDIR/sig" BIN_SIG="$TMPDIR/bin_sig" PUBLIC_KEY="$TMPDIR/public" if [ -z ${DEFAULT_CONNECTOR_URL} ]; then DEFAULT_CONNECTOR_URL="http://localhost:12345" fi PROG="../yubihsm-shell --connector=${DEFAULT_CONNECTOR_URL}" if [ "x$(uname)" = "xFreeBSD" ]; then DECODE="b64decode -pr" else DECODE="base64 --decode -i" fi echo "Hello World!" >"$DATA" OUTPUT=$($PROG -a generate-asymmetric -A ecp256 -csign-ecdsa -p password 2>&1) OBJ_ID=$(echo "$OUTPUT" | grep -o -E '0x[a-f0-9]{4}$') $PROG -a sign-ecdsa -i $OBJ_ID -A ecdsa-sha256 --in "$DATA" --out "$SIG" -p password $DECODE "$SIG" >"$BIN_SIG" $PROG -a get-public-key -i $OBJ_ID --out "$PUBLIC_KEY" -p password openssl dgst -sha256 -verify "$PUBLIC_KEY" -signature "$BIN_SIG" "$DATA" truncate -s 0 "$SIG" truncate -s 0 "$PUBLIC_KEY" #$PROG -a generate-asymmetric -i 0x1234 -A ecp256 -csign_ecdsa $PROG -a sign-ecdsa -i $OBJ_ID -A ecdsa-sha1 --in "$DATA" --out "$SIG" -p password $DECODE "$SIG" >"$BIN_SIG" $PROG -a get-public-key -i $OBJ_ID --out "$PUBLIC_KEY" -p password openssl dgst -sha1 -verify "$PUBLIC_KEY" -signature "$BIN_SIG" "$DATA" truncate -s 0 "$SIG" truncate -s 0 "$PUBLIC_KEY" OUTPUT=$($PROG -a generate-asymmetric -A ecp384 -csign-ecdsa -p password 2>&1) OBJ_ID=$(echo "$OUTPUT" | grep -o -E '0x[a-f0-9]{4}$') $PROG -a sign-ecdsa -i $OBJ_ID -A ecdsa-sha384 --in "$DATA" --out "$SIG" -p password $DECODE "$SIG" >"$BIN_SIG" $PROG -a get-public-key -i $OBJ_ID --out "$PUBLIC_KEY" -p password openssl dgst -sha384 -verify "$PUBLIC_KEY" -signature "$BIN_SIG" "$DATA" truncate -s 0 "$SIG" truncate -s 0 "$PUBLIC_KEY" OUTPUT=$($PROG -a generate-asymmetric -A ecp521 -csign-ecdsa -p password 2>&1) OBJ_ID=$(echo "$OUTPUT" | grep -o -E '0x[a-f0-9]{4}$') $PROG -a sign-ecdsa -i $OBJ_ID -A ecdsa-sha512 --in "$DATA" --out "$SIG" -p password $DECODE "$SIG" >"$BIN_SIG" $PROG -a get-public-key -i $OBJ_ID --out "$PUBLIC_KEY" -p password openssl dgst -sha512 -verify "$PUBLIC_KEY" -signature "$BIN_SIG" "$DATA" $PROG -a blink-device -p password $PROG -a get-device-info $PROG -a get-storage-info -p password $PROG -a get-option -p password --opt-name command-audit $PROG -a put-option -p password --opt-name command-audit --opt-value 0101 $PROG -a get-option -p password --opt-name force-audit $PROG -a put-option -p password --opt-name force-audit --opt-value 00 $PROG -a get-option -p password --opt-name algorithm-toggle # no test for putting algorithm-toggle as that requires and empty device yubihsm-shell-2.6.0/src/tests/wrapped_tests.sh0000755000175100001770000003711414666527773021062 0ustar runnerdocker#!/usr/bin/env bash # # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # if [[ ! -z "$DEBUG" ]]; then set -x fi set -eo pipefail if [ -z ${DEFAULT_CONNECTOR_URL} ]; then DEFAULT_CONNECTOR_URL="http://localhost:12345" fi readonly TMPDIR=$(mktemp -d) trap 'rm -rf "$TMPDIR"' INT TERM EXIT echo ">>> TMPDIR=$TMPDIR" readonly YHSHELL="../yubihsm-shell --connector=${DEFAULT_CONNECTOR_URL}" readonly YHWRAP="../../yhwrap/yubihsm-wrap" put_yhwrapped_authkey() { local -r wrapid="0xdead" local -r wrapkey="$TMPDIR/${FUNCNAME[0]}_wrapkey" local -r authid="0xbeef" local -r authkey="$TMPDIR/${FUNCNAME[0]}_authkey" local -r passfile="$TMPDIR/${FUNCNAME[0]}_passfile" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" && { echo "${FUNCNAME[0]}: delete wrapkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" } echo "${FUNCNAME[0]}: put-wrap-key" openssl rand 32 > "$wrapkey" $YHSHELL --action="put-wrap-key" --password="password" --authkey="1" \ --object-id="$wrapid" --label="${FUNCNAME[0]}" --domains="all" \ --capabilities="all" --delegated="all" --in="$wrapkey" --informat="binary" echo "${FUNCNAME[0]}: creating authkey" echo "password" > "$passfile" $YHWRAP --algorithm="aes128-yubico-authentication" --capabilities="all" \ --delegated="all" --domains="all" --id="$authid" --in="$passfile" \ --out="$authkey" --label="${FUNCNAME[0]}" --wrapkey="$wrapkey" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$authid" --object-type="authentication-key" && { echo "${FUNCNAME[0]}: delete authkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$authid" --object-type="authentication-key" } echo "${FUNCNAME[0]}: put-wrapped authkey" $YHSHELL --action="put-wrapped" --password="password" --authkey="1" \ --wrap-id="$wrapid" --in="$authkey" --informat="base64" echo "${FUNCNAME[0]}: using put-wrapped authkey" $YHSHELL --action="get-pseudo-random" --password="$passfile" --authkey="$authid" \ --count=1 --out=/dev/null } put_yhwrapped_authkey_fail_cap() { local -r wrapid="0xdead" local -r wrapkey="$TMPDIR/${FUNCNAME[0]}_wrapkey" local -r authid="0xbeef" local -r authkey="$TMPDIR/${FUNCNAME[0]}_authkey" local -r passfile="$TMPDIR/${FUNCNAME[0]}_passfile" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" && { echo "${FUNCNAME[0]}: delete wrapkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" } openssl rand 16 > "$wrapkey" echo "${FUNCNAME[0]}: creating wrapkey" $YHSHELL --action="put-wrap-key" --password="password" --authkey="1" \ --object-id="$wrapid" --label="${FUNCNAME[0]}" --domains="all" \ --capabilities="all" --delegated="none" \ --in="$wrapkey" --informat="binary" echo "${FUNCNAME[0]}: creating authkey" echo "password" > "$passfile" $YHWRAP --algorith="aes128-yubico-authentication" \ --capabilities="all" --delegated="all" \ --domains="all" --id="$authid" --in="$passfile" --out="$authkey" \ --label="${FUNCNAME[0]}" --wrapkey="$wrapkey" echo "${FUNCNAME[0]}: put-wrapped authkey" ! $YHSHELL --action="put-wrapped" --password="password" --authkey="1" \ --wrap-id="$wrapid" --in="$authkey" --informat="base64" if [[ "${PIPESTATUS[0]}" != "1" ]]; then echo "put_yhwrapped_authkey_fail_caps: put-wrapped should have failed" exit 1 fi } put_yhwrapped_authkey_fail_domain() { local -r wrapid="0xdead" local -r wrapkey="$TMPDIR/${FUNCNAME[0]}_wrapkey" local -r authid="0xbeef" local -r authkey="$TMPDIR/${FUNCNAME[0]}_authkey" local -r passfile="$TMPDIR/${FUNCNAME[0]}_passfile" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" && { echo "${FUNCNAME[0]}: delete wrapkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" } echo "${FUNCNAME[0]}: creating restricted wrapkey" openssl rand 24 > "$wrapkey" $YHSHELL --action="put-wrap-key" --password="password" --authkey="1" \ --object-id="$wrapid" --label="${FUNCNAME[0]}" --domains="2" \ --capabilities="all" --delegated="all" \ --in="$wrapkey" --informat="binary" echo "${FUNCNAME[0]}: creating authkey" echo "password" > "$passfile" $YHWRAP --algorith="aes128-yubico-authentication" \ --capabilities="all" --delegated="all" \ --domains="all" --id="$authid" --in="$passfile" --out="$authkey" \ --label="${FUNCNAME[0]}" --wrapkey="$wrapkey" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$authid" --object-type="authentication-key" && { echo "${FUNCNAME[0]}: delete authkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$authid" --object-type="authentication-key" } echo "${FUNCNAME[0]}: put-wrapped authkey" $YHSHELL --action="put-wrapped" --password="password" --authkey="1" \ --wrap-id="$wrapid" --in="$authkey" --informat="base64" # NOTE(thorduri): Domains just get filtered. local domains domains="$( $YHSHELL --action="get-object-info" --password="password" \ --authkey="1" --object-type="authentication-key" --object-id="$authid" | grep "^id" \ | awk -F: '{print $7}' | awk -F, '{print $1}' | tr -d '[:space:]' )" if [[ "$domains" != "2" ]]; then echo "${FUNCNAME[0]}: domains not filtered: expected 2 got $domains" exit 1 fi } put_yhwrapped_asymmetric_rsa() { local -r wrapid="0xdead" local -r wrapkey="$TMPDIR/${FUNCNAME[0]}_wrapkey" local -r keyid="0xfefe" local -r keyfile="$TMPDIR/${FUNCNAME[0]}_keyfile.pem" local -r keyfilew="$TMPDIR/${FUNCNAME[0]}_keyfile.wrapped" local -r sigbuf="$TMPDIR/${FUNCNAME[0]}_sigbuf" local -r signature="$TMPDIR/${FUNCNAME[0]}_signature" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" && { echo "${FUNCNAME[0]}: delete wrapkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" } echo "${FUNCNAME[0]}: creating wrapkey" openssl rand 16 > "$wrapkey" $YHSHELL --action="put-wrap-key" --password="password" --authkey="1" \ --object-id="$wrapid" --label="${FUNCNAME[0]}" --domains="all" \ --capabilities="all" --delegated="all" \ --in="$wrapkey" --informat="binary" local -r rsa=( "2048" "3072" "4096" ) for size in "${rsa[@]}"; do $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$keyid" --object-type="asymmetric-key" && { echo "${FUNCNAME[0]}: delete rsa key" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$keyid" --object-type="asymmetric-key" } echo "${FUNCNAME[0]}: creating rsa$size key" openssl genrsa -out "$keyfile.$size" $size $YHWRAP --algorithm="rsa$size" \ --capabilities="all" --delegated="all" \ --domains="all" --id="$keyid" --in="$keyfile.$size" \ --out="$keyfilew.$size" --label="${FUNCNAME[0]}" --wrapkey="$wrapkey" echo "${FUNCNAME[0]}: put-wrapped rsa$size asymmetric" $YHSHELL --action="put-wrapped" --password="password" --authkey="1" \ --wrap-id="$wrapid" --in="$keyfilew.$size" --informat="base64" echo "${FUNCNAME[0]}: comparing pubs rsa$size" openssl rsa -in "$keyfile.$size" -pubout > "$keyfile.$size.pub" $YHSHELL --action="get-public-key" --password="password" --authkey="1" \ --object-id="$keyid" --out="$keyfile.$size.pub.shell" diff -u "$keyfile.$size.pub" "$keyfile.$size.pub.shell" openssl rand 1024 > "$sigbuf" echo "${FUNCNAME[0]}: sign-pkcs1v15 rsa$size rsa-pkcs1-sha256" $YHSHELL --action="sign-pkcs1v15" --password="password" --authkey="1" \ --object-id="$keyid" --algorithm "rsa-pkcs1-sha256" --in="$sigbuf" --out "$signature.$size" --outformat="bin" echo "${FUNCNAME[0]}: verifying rsa$size sha256 signature" openssl dgst -sha256 -verify "$keyfile.$size.pub" -signature "$signature.$size" "$sigbuf" done } put_yhwrapped_asymmetric_ecdsa() { local -r wrapid="0xdead" local -r wrapkey="$TMPDIR/${FUNCNAME[0]}_wrapkey" local -r keyid="0xfefe" local -r keyfile="$TMPDIR/${FUNCNAME[0]}_keyfile.pem" local -r keyfilew="$TMPDIR/${FUNCNAME[0]}_keyfile.wrapped" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" && { echo "${FUNCNAME[0]}: delete wrapkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" } echo "${FUNCNAME[0]}: creating wrapkey" openssl rand 16 > "$wrapkey" $YHSHELL --action="put-wrap-key" --password="password" --authkey="1" \ --object-id="$wrapid" --label="${FUNCNAME[0]}" --domains="all" \ --capabilities="all" --delegated="all" \ --in="$wrapkey" --informat="binary" curves="secp256k1 secp384r1 secp521r1 prime256v1" secp256k1=eck256 secp384r1=ecp384 secp521r1=ecp521 prime256v1=ecp256 if openssl ecparam -list_curves | grep -q brainpoolP256r1; then curves="$curves brainpoolP256r1 brainpoolP384r1 brainpoolP512r1" brainpoolP256r1=ecbp256 brainpoolP384r1=ecbp384 brainpoolP512r1=ecbp512 fi for curve in $curves; do $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$keyid" --object-type="asymmetric-key" && { echo "${FUNCNAME[0]}: delete ec key" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$keyid" --object-type="asymmetric-key" } echo "${FUNCNAME[0]}: creating ${!curve} key" openssl ecparam -genkey -noout -name $curve > "$keyfile.$curve" $YHWRAP --algorithm="${!curve}" \ --capabilities="all" --delegated="all" \ --domains="all" --id="$keyid" --in="$keyfile.$curve" \ --out="$keyfilew.$curve" --label="${FUNCNAME[0]}" --wrapkey="$wrapkey" echo "${FUNCNAME[0]}: put-wrapped ${!curve}" $YHSHELL --action="put-wrapped" --password="password" --authkey="1" \ --wrap-id="$wrapid" --in="$keyfilew.$curve" --informat="base64" echo "${FUNCNAME[0]}: comparing pubs ${!curve}" openssl ec -in "$keyfile.$curve" -pubout > "$keyfile.$curve.pub" $YHSHELL --action="get-public-key" --password="password" --authkey="1" \ --object-id="$keyid" --out="$keyfile.$curve.pub.shell" diff -u "$keyfile.$curve.pub" "$keyfile.$curve.pub.shell" done } put_yhwrapped_asymmetric_eddsa() { if [ $(openssl list -public-key-methods | grep -i ed25519 -c) -eq 0 ]; then echo "OpenSSL version without Ed25519, skipping put_yhwrapped_asymmetric_eddsa" return fi local -r edkeyid="0xeded" local -r wrapid="0xdead" local -r wrapkey="$TMPDIR/${FUNCNAME[0]}_wrapkey" local -r keyid="0xfefe" local -r keyfile="$TMPDIR/${FUNCNAME[0]}_keyfile.pem" local -r keyfilew="$TMPDIR/${FUNCNAME[0]}_keyfile.wrapped" local -r sigfile1="$TMPDIR/${FUNCNAME[0]}_sig_1" local -r sigfile2="$TMPDIR/${FUNCNAME[0]}_sig_2" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" && { echo "${FUNCNAME[0]}: delete wrapkey" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$wrapid" --object-type="wrap-key" } echo "${FUNCNAME[0]}: creating wrapkey" openssl rand 16 > "$wrapkey" $YHSHELL --action="put-wrap-key" --password="password" --authkey="1" \ --object-id="$wrapid" --label="${FUNCNAME[0]}" --domains="all" \ --capabilities="all" --delegated="all" \ --in="$wrapkey" --informat="binary" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$keyid" --object-type="asymmetric-key" && { echo "${FUNCNAME[0]}: delete ed key" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$keyid" --object-type="asymmetric-key" } echo "${FUNCNAME[0]}: creating ed key" openssl genpkey -algorithm Ed25519 -out "$keyfile" $YHSHELL --action="get-object-info" --password="password" --authkey="1" \ --object-id="$edkeyid" --object-type="asymmetric-key" && { echo "${FUNCNAME[0]}: delete imported ed key" $YHSHELL --action="delete-object" --password="password" --authkey="1" \ --object-id="$edkeyid" --object-type="asymmetric-key" } echo "${FUNCNAME[0]}: importing ed key" $YHSHELL --action="put-asymmetric-key" --password="password" --authkey="1" \ --object-id="$edkeyid" --label="${FUNCNAME[0]}" --domains="all" \ --capabilities="all" \ --in="$keyfile" --informat="binary" echo "${FUNCNAME[0]}: signing with ed key" rm -f $sigfile1 $YHSHELL --action="sign-eddsa" --object-id="$edkeyid" --algorithm="ed25519" --in="$wrapkey" --out="$sigfile1" --password="password" $YHWRAP --algorithm="ed25519" \ --capabilities="all" --delegated="all" \ --domains="all" --id="$keyid" --in="$keyfile" \ --out="$keyfilew" --label="${FUNCNAME[0]}" --wrapkey="$wrapkey" echo "${FUNCNAME[0]}: put-wrapped ed25519" $YHSHELL --action="put-wrapped" --password="password" --authkey="1" \ --wrap-id="$wrapid" --in="$keyfilew" --informat="base64" echo "${FUNCNAME[0]}: comparing pubs ed25519" openssl pkey -in "$keyfile" -pubout > "$keyfile.pub" $YHSHELL --action="get-public-key" --password="password" --authkey="1" \ --object-id="$keyid" --out="$keyfile.pub.shell" diff -u "$keyfile.pub" "$keyfile.pub.shell" echo "${FUNCNAME[0]}: signing with wrapped ed key" rm -f "$sigfile2" $YHSHELL --action="sign-eddsa" --object-id="$keyid" --algorithm="ed25519" --in="$wrapkey" --out="$sigfile2" --password="password" diff -u "$sigfile1" "$sigfile2" } main() { put_yhwrapped_authkey put_yhwrapped_authkey_fail_cap put_yhwrapped_authkey_fail_domain put_yhwrapped_asymmetric_rsa put_yhwrapped_asymmetric_ecdsa put_yhwrapped_asymmetric_eddsa } main "$@" yubihsm-shell-2.6.0/src/tests/data.txt0000644000175100001770000000001514666527773017277 0ustar runnerdockerHello World! yubihsm-shell-2.6.0/src/tests/yubihsm_shell_tests.c0000644000175100001770000001332014666527773022065 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #define EXIT_SKIPPED 77; yh_device **devices; uint16_t n_devices; yh_session *ses; typedef struct { uint16_t len; double min; double max; double tot; } repetition_stats; #define DEFAULT_KEY \ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f" #define N_REPS \ 8 // Data length for repetition i is 2^(1 + i) for i in [0, N_REPS-1] #define N_ITERATIONS 1000 #define ECHO_BYTE 0x0f int main() { yh_rc yrc; uint8_t key_enc[YH_KEY_LEN]; uint8_t key_mac[YH_KEY_LEN]; uint8_t key_dek[YH_KEY_LEN]; uint8_t host_challenge[YH_HOST_CHAL_LEN] = {0}; uint8_t yh_context[YH_CONTEXT_LEN]; struct timeval before, after; double this; repetition_stats rs[N_REPS], rs2[N_REPS]; uint8_t data[YH_MSG_BUF_SIZE]; uint8_t response[YH_MSG_BUF_SIZE]; uint16_t response_len; uint16_t len; uint8_t verbosity = 0; // YH_VERB_USB | YH_VERB_CRYPTO | YH_VERB_INTERMEDIATE // | YH_VERB_INFO | YH_VERB_ERR; yrc = yh_init(&devices, &n_devices); if (yrc != YH_SUCCESS) { fprintf(stderr, "Unable to initialize\n"); fprintf(stderr, "(Typically this happens if you don't have permissions to " "open the device\n"); fprintf(stderr, "try re-running as root/Administrator)\n"); return EXIT_SKIPPED; } if (n_devices == 0) { fprintf(stderr, "No suitable device found. Skipping this test\n"); return EXIT_SKIPPED; } yh_set_verbosity(verbosity); memset(data, ECHO_BYTE, 1024); // Plain commands len = 4; for (uint16_t rep = 0; rep < N_REPS; rep++) { len *= 2; rs[rep].len = len; fprintf(stderr, "now doing plain with len %d\n", len); for (uint16_t i = 0; i < N_ITERATIONS; i++) { response_len = sizeof(response); gettimeofday(&before, NULL); yrc = yh_send_plain_msg(devices[0], YHC_ECHO, data, rs[rep].len, response, &response_len); gettimeofday(&after, NULL); this = (after.tv_sec - before.tv_sec) * 1000; this += ((double) (after.tv_usec - before.tv_usec)) / 1000; if (i == 0) { rs[rep].max = rs[rep].min = this; rs[rep].tot = 0; } else { if (this > rs[rep].max) { rs[rep].max = this; } if (this < rs[rep].min) { rs[rep].min = this; } } rs[rep].tot += this; if (rs[rep].len != response_len || memcmp(data, response, rs[rep].len) != 0) { fprintf(stderr, "Data mismatch\n"); return EXIT_FAILURE; } } } // Auth commands memcpy(key_enc, DEFAULT_KEY, YH_KEY_LEN); // TODO: fix memcpy(key_mac, DEFAULT_KEY, YH_KEY_LEN); // TODO: fix memcpy(key_dek, DEFAULT_KEY, YH_KEY_LEN); // TODO: fix yrc = yh_open_device(devices[0]); if (yrc != YH_SUCCESS) { fprintf(stderr, "Unable to open device: %s\n", yh_strerror(yrc)); return EXIT_FAILURE; } yrc = yh_create_session(devices[0], 0, host_challenge, key_enc, 16, key_mac, 16, yh_context, &ses); if (yrc != YH_SUCCESS) { fprintf(stderr, "Failed to create session: %s\n", yh_strerror(yrc)); return EXIT_FAILURE; } len = 4; for (uint16_t rep = 0; rep < N_REPS; rep++) { len *= 2; rs2[rep].len = len; fprintf(stderr, "now doing auth with len %d\n", len); for (uint16_t i = 0; i < N_ITERATIONS; i++) { response_len = sizeof(response); gettimeofday(&before, NULL); yrc = yh_send_secure_msg(ses, YHC_ECHO, data, rs2[rep].len, response, &response_len); gettimeofday(&after, NULL); if (yrc != YH_SUCCESS) { fprintf(stderr, "Failed to send message: %d, %s\n", yrc, yh_strerror(yrc)); return EXIT_FAILURE; } this = (after.tv_sec - before.tv_sec) * 1000; this += ((double) (after.tv_usec - before.tv_usec)) / 1000; if (i == 0) { rs2[rep].max = rs2[rep].min = this; rs2[rep].tot = 0; } else { if (this > rs2[rep].max) { rs2[rep].max = this; } if (this < rs2[rep].min) { rs2[rep].min = this; } } rs2[rep].tot += this; if (rs2[rep].len != response_len || memcmp(data, response, rs2[rep].len) != 0) { fprintf(stderr, "Data mismatch\n"); return EXIT_FAILURE; } } } yh_exit(devices, n_devices); fprintf(stdout, "Iterations %d\n", N_ITERATIONS); fprintf(stdout, "| Len | min [ms] | max [ms] | avg [ms] | type |\n"); fprintf(stdout, "---------------------------------------------------\n"); for (uint16_t i = 0; i < N_REPS; i++) { fprintf(stdout, "| %6d | %8.02f | %8.02f | %8.02f | plain |\n", rs[i].len, rs[i].min, rs[i].max, rs[i].tot / N_ITERATIONS); } for (uint16_t i = 0; i < N_REPS; i++) { fprintf(stdout, "| %6d | %8.02f | %8.02f | %8.02f | auth |\n", rs2[i].len, rs2[i].min, rs2[i].max, rs2[i].tot / N_ITERATIONS); } return EXIT_SUCCESS; } yubihsm-shell-2.6.0/src/main.c0000644000175100001770000034367414666527773015600 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include #include #include #include #include "util.h" #include "parsing.h" #include "commands.h" #include "insecure_memzero.h" #include //#include #define PROMPT "yubihsm> " #define ARGS_BUFFER_SIZE 4096 #define COMPLETION_CANDIDATES 256 #define MAX_COMMAND_NAME 32 #define MAX_ARGUMENTS 32 #include "yubihsm-shell.h" #define SPACES " \f\n\r\t\v" #ifdef __WIN32 #include #include #include // TODO: cheat on windows, cheat better? #define S_ISLNK S_ISREG #else #include #include #include #include #include #include History *g_hist; #endif #ifdef _MSVC #define S_ISREG(m) (((m) &S_IFMT) == S_IFREG) #define strcasecmp _stricmp #define strncasecmp _strnicmp #endif #define UNUSED(x) (void) (x) #define LIB_SUCCEED_OR_DIE(x, s) \ if ((x) != YHR_SUCCESS) { \ fprintf(stderr, s "%s\n", yh_strerror(x)); \ rc = EXIT_FAILURE; \ break; \ } #define COM_SUCCEED_OR_DIE(x, s) \ if ((x) != 0) { \ fprintf(stderr, s "\n"); \ rc = EXIT_FAILURE; \ break; \ } static bool calling_device = false; static yubihsm_context g_ctx = {0}; int yh_com_help(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_history(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_quit(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_informat(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_outformat(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); typedef struct Command Command; // NOTE(adma): supported values for the argument list are as follow // u: unsigned integer (either decimal or hex if starts with 0x) // w: unsigned short // b: unsigned byte // f: out filename // F: in filename // s: string // e: session struct Command { char *name; /* Command name to match against */ CommandFunction *func; /* Documentation for the function */ char *args; /* Argument string */ cmd_format in_fmt; /* Default input format for command */ cmd_format out_fmt; /* Default output format for command */ char *doc; /* Function to call to do the job */ Command *subcommands; /* List of subcommands */ Command *next; /* Pointer to next command */ }; typedef Command *CommandList; // NOTE(adma): push command to list and return the new head static Command *register_command(CommandList list, Command command) { Command *c = calloc(1, sizeof(Command)); if (c == NULL) { fprintf(stderr, "Failed to allocate memory\n"); exit(EXIT_FAILURE); } assert(strlen(command.name) <= MAX_COMMAND_NAME); memcpy(c, &command, sizeof(Command)); c->next = list; return c; } static void register_subcommand(Command *parent, Command command) { Command *c = malloc(sizeof(Command)); if (c == NULL) { fprintf(stderr, "Failed to allocate memory\n"); exit(EXIT_FAILURE); } memcpy(c, &command, sizeof(Command)); c->next = parent->subcommands; parent->subcommands = c; } static CommandList msort_list(CommandList list) { Command *left; Command *right; Command *e; int in_size; int left_size; int right_size; // NOTE(adma): do nothing on an empty list if (!list) { return NULL; } in_size = 1; while (1) { Command *tail = NULL; left = list; list = NULL; int n_merges = 0; while (left != NULL) { n_merges++; right = left; left_size = 0; for (int i = 0; i < in_size; i++) { left_size++; right = right->next; if (right == NULL) { break; } } right_size = in_size; while (left_size > 0 || (right_size > 0 && right)) { if (left_size == 0) { e = right; right = right->next; right_size--; } else if (right_size == 0 || !right) { e = left; left = left->next; left_size--; } else if (strcmp(left->name, right->name) <= 0) { e = left; left = left->next; left_size--; } else { e = right; right = right->next; right_size--; } if (tail) { tail->next = e; } else { list = e; } tail = e; } left = right; } if (tail != NULL) { tail->next = NULL; } if (n_merges <= 1) { return list; } in_size *= 2; } } static void create_command_list(CommandList *c) { // NOTE(adma): initialize *c = NULL; *c = register_command(*c, (Command){"audit", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Deal with audit log", NULL, NULL}); register_subcommand(*c, (Command){"get", yh_com_audit, "e:session,F:file=-", fmt_ASCII, fmt_nofmt, "Extract log entries", NULL, NULL}); register_subcommand(*c, (Command){"set", yh_com_set_log_index, "e:session,w:index", fmt_nofmt, fmt_nofmt, "Set the log index", NULL, NULL}); *c = register_command(*c, (Command){"connect", yh_com_connect, NULL, fmt_nofmt, fmt_nofmt, "Connect to a connector", NULL, NULL}); *c = register_command(*c, (Command){"debug", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Change debug settings", NULL, NULL}); register_subcommand(*c, (Command){"all", yh_com_debug_all, NULL, fmt_nofmt, fmt_nofmt, "Enable all debug messages", NULL, NULL}); register_subcommand(*c, (Command){"crypto", yh_com_debug_crypto, NULL, fmt_nofmt, fmt_nofmt, "Toggle crypto debug messages", NULL, NULL}); register_subcommand(*c, (Command){"error", yh_com_debug_error, NULL, fmt_nofmt, fmt_nofmt, "Toggle error debug messages", NULL, NULL}); register_subcommand(*c, (Command){"info", yh_com_debug_info, NULL, fmt_nofmt, fmt_nofmt, "Toggle info debug messages", NULL, NULL}); register_subcommand(*c, (Command){"intermediate", yh_com_debug_intermediate, NULL, fmt_nofmt, fmt_nofmt, "Toggle intermediate debug messages", NULL, NULL}); register_subcommand(*c, (Command){"none", yh_com_debug_none, NULL, fmt_nofmt, fmt_nofmt, "Disable all debug messages", NULL, NULL}); register_subcommand(*c, (Command){"raw", yh_com_debug_raw, NULL, fmt_nofmt, fmt_nofmt, "Toggle raw debug messages", NULL, NULL}); *c = register_command(*c, (Command){"decrypt", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Decrypt data", NULL, NULL}); register_subcommand(*c, (Command){"pkcs1v1_5", yh_com_decrypt_pkcs1v1_5, "e:session,w:key_id,i:data=-", fmt_binary, fmt_base64, "Decrypt data using RSAES-PKCS#1v1.5", NULL, NULL}); register_subcommand( *c, (Command){"oaep", yh_com_decrypt_oaep, "e:session,w:key_id,a:algorithm,i:data=-,s:label=", fmt_binary, fmt_base64, "Decrypt data using RSAES-OAEP", NULL, NULL}); register_subcommand(*c, (Command){"aesccm", yh_com_decrypt_aesccm, "e:session,w:key_id,i:data=-", fmt_base64, fmt_binary, "Decrypt data using Yubico-AES-CCM", NULL, NULL}); register_subcommand( *c, (Command){"aescbc", yh_com_decrypt_aes_cbc, "e:session,w:key_id,s:iv,i:data=-", fmt_base64, fmt_binary, "Decrypt data using an AES symmetric key in CBC mode", NULL, NULL}); register_subcommand( *c, (Command){"aesecb", yh_com_decrypt_aes_ecb, "e:session,w:key_id,i:data=-", fmt_base64, fmt_binary, "Decrypt data using an AES symmetric key in ECB mode", NULL, NULL}); *c = register_command(*c, (Command){"derive", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Drive data", NULL, NULL}); register_subcommand(*c, (Command){"ecdh", yh_com_derive_ecdh, "e:session,w:key_id,i:pubkey=-", fmt_PEM, fmt_hex, "Perform a ECDH key exchange", NULL, NULL}); *c = register_command(*c, (Command){"encrypt", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Encrypt data", NULL, NULL}); register_subcommand(*c, (Command){"aesccm", yh_com_encrypt_aesccm, "e:session,w:key_id,i:data=-", fmt_binary, fmt_base64, "Encrypt data using Yubico-AES-CCM", NULL, NULL}); register_subcommand( *c, (Command){"aescbc", yh_com_encrypt_aes_cbc, "e:session,w:key_id,s:iv,i:data=-", fmt_binary, fmt_base64, "Encrypt data using an AES symmetric key in CBC mode", NULL, NULL}); register_subcommand( *c, (Command){"aesecb", yh_com_encrypt_aes_ecb, "e:session,w:key_id,i:data=-", fmt_binary, fmt_base64, "Encrypt data using an AES symmetric key in ECB mode", NULL, NULL}); *c = register_command(*c, (Command){"disconnect", yh_com_disconnect, NULL, fmt_nofmt, fmt_nofmt, "Disconnect from a connector", NULL, NULL}); *c = register_command(*c, (Command){"echo", yh_com_echo, "e:session,b:byte,w:count", fmt_nofmt, fmt_nofmt, "Send an ECHO command over a given session", NULL, NULL}); *c = register_command(*c, (Command){"generate", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Generate key", NULL, NULL}); register_subcommand(*c, (Command){"asymmetric", yh_com_generate_asymmetric, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,a:algorithm", fmt_nofmt, fmt_nofmt, "Generate an asymmetric key", NULL, NULL}); register_subcommand(*c, (Command){"hmackey", yh_com_generate_hmac, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,a:algorithm", fmt_nofmt, fmt_nofmt, "Generate HMAC key", NULL, NULL}); register_subcommand( *c, (Command){"wrapkey", yh_com_generate_wrap, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,c:delegated_capabilities,a:algorithm", fmt_nofmt, fmt_nofmt, "Generate wrap key", NULL, NULL}); register_subcommand(*c, (Command){"otpaeadkey", yh_com_generate_otp_aead_key, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,a:algorithm,u:nonce_id", fmt_nofmt, fmt_nofmt, "Generate OTP AEAD key", NULL, NULL}); register_subcommand(*c, (Command){"symmetric", yh_com_generate_symmetric, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,a:algorithm", fmt_nofmt, fmt_nofmt, "Generate a symmetric key", NULL, NULL}); *c = register_command(*c, (Command){"get", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Retrieve data", NULL, NULL}); register_subcommand(*c, (Command){"opaque", yh_com_get_opaque, "e:session,w:object_id,F:file=-", fmt_nofmt, fmt_binary, "Get an opaque object", NULL, NULL}); register_subcommand(*c, (Command){"option", yh_com_get_option, "e:session,o:option", fmt_nofmt, fmt_nofmt, // FIXME: output "Get a global option value", NULL, NULL}); register_subcommand(*c, (Command){"random", yh_com_get_random, "e:session,w:count,F:out=-", fmt_nofmt, fmt_hex, "Get pseudo-random bytes", NULL, NULL}); register_subcommand(*c, (Command){"storage", yh_com_get_storage, "e:session", fmt_nofmt, fmt_nofmt, "Get storages stats", NULL, NULL}); register_subcommand(*c, (Command){"pubkey", yh_com_get_pubkey, "e:session,w:key_id,t:key_type=asymmetric-key,F:file=-", fmt_nofmt, fmt_PEM, "Get a public key", NULL, NULL}); register_subcommand(*c, (Command){"objectinfo", yh_com_get_object_info, "e:session,w:id,t:type", fmt_nofmt, fmt_nofmt, "Get information about an object", NULL, NULL}); register_subcommand(*c, (Command){"wrapped", yh_com_get_wrapped, "e:session,w:wrapkey_id,t:type,w:id,b:include_seed=0,F:file=-", fmt_nofmt, fmt_base64, "Get an object under wrap", NULL, NULL}); register_subcommand(*c, (Command){"rsa_wrapped", yh_com_get_rsa_wrapped, "e:session,w:wrapkey_id,t:type,w:id,a:aes=aes256,a:hash=rsa-oaep-sha256,a:mgf1=mgf1-sha256,F:file=-", fmt_nofmt, fmt_binary, "Get an object under RSA wrap", NULL, NULL}); register_subcommand(*c, (Command){"rsa_wrapped_key", yh_com_get_rsa_wrapped_key, "e:session,w:wrapkey_id,t:type,w:id,a:aes=aes256,a:hash=rsa-oaep-sha256,a:mgf1=mgf1-sha256,F:file=-", fmt_nofmt, fmt_binary, "Get a (a)symmetric key under RSA wrap", NULL, NULL}); register_subcommand(*c, (Command){"deviceinfo", yh_com_get_device_info, NULL, fmt_nofmt, fmt_nofmt, "Extract the version number, serial number " "and supported algorithms", NULL, NULL}); register_subcommand(*c, (Command){"template", yh_com_get_template, "e:session,w:object_id,F:out=-", fmt_nofmt, fmt_base64, "Get a template object", NULL, NULL}); register_subcommand(*c, (Command){"devicepubkey", yh_com_get_device_pubkey, NULL, fmt_nofmt, fmt_PEM, "Get the device public key for asymmetric " "authentication", NULL, NULL}); *c = register_command(*c, (Command){"help", yh_com_help, "s:command=", fmt_nofmt, fmt_nofmt, "Display help text", NULL, NULL}); *c = register_command(*c, (Command){"history", yh_com_history, NULL, fmt_nofmt, fmt_nofmt, "Display the command history", NULL, NULL}); *c = register_command(*c, (Command){"list", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "List information", NULL, NULL}); register_subcommand(*c, (Command){"capabilities", yh_com_list_capabilities, NULL, fmt_nofmt, fmt_nofmt, "Prints a list of possible capabilities", NULL, NULL}); register_subcommand(*c, (Command){"algorithms", yh_com_list_algorithms, NULL, fmt_nofmt, fmt_nofmt, "Prints a list of possible algorithms", NULL, NULL}); register_subcommand(*c, (Command){"types", yh_com_list_types, NULL, fmt_nofmt, fmt_nofmt, "Prints a list of possible types", NULL, NULL}); register_subcommand(*c, (Command){"sessions", yh_com_list_sessions, NULL, fmt_nofmt, fmt_nofmt, "List the open session", NULL, NULL}); register_subcommand(*c, (Command){"objects", yh_com_list_objects, "e:session,w:id=0,t:type=any,d:domains=0,c:" "capabilities=0,a:algorithm=any,s:label=", fmt_nofmt, fmt_nofmt, "List objects according to filter", NULL, NULL}); *c = register_command(*c, (Command){"plain", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Send unencrypted and unauthenticated commands", NULL, NULL}); register_subcommand(*c, (Command){"echo", yh_com_pecho, "b:byte,w:count", fmt_nofmt, fmt_nofmt, "Send a plain echo command", NULL, NULL}); *c = register_command(*c, (Command){"put", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Store data", NULL, NULL}); register_subcommand(*c, (Command){"asymmetric", yh_com_put_asymmetric, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,i:key=-", fmt_PEM, fmt_nofmt, "Store an asymmetric key", NULL, NULL}); register_subcommand(*c, (Command){"authkey", yh_com_put_authentication, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,c:delegated_capabilities,i:" "password=-", fmt_password, fmt_nofmt, "Store an authentication key", NULL, NULL}); register_subcommand(*c, (Command){"authkey_asym", yh_com_put_authentication_asym, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,c:delegated_capabilities,i:" "pubkey=-", fmt_PEM, fmt_nofmt, "Store an asymmetric authentication key", NULL, NULL}); register_subcommand(*c, (Command){"opaque", yh_com_put_opaque, "e:session,w:object_id,s:label,d:domains,c:" "capabilities,a:algorithm,i:data=-", fmt_binary, fmt_nofmt, "Store an opaque object", NULL, NULL}); register_subcommand(*c, (Command){"option", yh_com_put_option, "e:session,o:option,i:data", fmt_hex, fmt_nofmt, "Set a global option value", NULL, NULL}); register_subcommand(*c, (Command){"hmackey", yh_com_put_hmac, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,a:algorithm,i:key", fmt_hex, fmt_nofmt, "Store a HMAC key", NULL, NULL}); register_subcommand(*c, (Command){"wrapkey", yh_com_put_wrapkey, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,c:delegated_capabilities,i:key", fmt_hex, fmt_nofmt, "Store a wrapping key", NULL, NULL}); register_subcommand(*c, (Command){"rsa_wrapkey", yh_com_put_rsa_wrapkey, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,c:delegated_capabilities,i:key=-", fmt_PEM, fmt_nofmt, "Store an RSA wrapping key", NULL, NULL}); register_subcommand(*c, (Command){"pub_wrapkey", yh_com_put_public_wrapkey, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,c:delegated_capabilities,i:key=-", fmt_PEM, fmt_nofmt, "Store an RSA wrapping key", NULL, NULL}); register_subcommand(*c, (Command){"wrapped", yh_com_put_wrapped, "e:session,w:wrapkey_id,i:data=-", fmt_base64, fmt_nofmt, "Store a wrapped object", NULL, NULL}); register_subcommand(*c, (Command){"rsa_wrapped", yh_com_put_rsa_wrapped, "e:session,w:wrapkey_id,a:hash=rsa-oaep-sha256,a:mgf1=mgf1-sha256,i:data=-", fmt_binary, fmt_nofmt, "Store a wrapped object", NULL, NULL}); register_subcommand(*c, (Command){"rsa_wrapped_key", yh_com_put_rsa_wrapped_key, "e:session,w:wrapkey_id,t:type,w:key_id,a:algorithm,s:label,d:domains,c:capabilities,a:hash=rsa-oaep-sha256,a:mgf1=mgf1-sha256,i:data=-", fmt_binary, fmt_nofmt, "Store a wrapped object", NULL, NULL}); register_subcommand(*c, (Command){"template", yh_com_put_template, "e:session,w:object_id,s:label,d:domains,c:" "capabilities,a:algorithm,i:data=-", fmt_base64, fmt_nofmt, "Store a template object", NULL, NULL}); register_subcommand(*c, (Command){"otpaeadkey", yh_com_put_otp_aead_key, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,u:nonce_id,i:key", fmt_hex, fmt_nofmt, "Store a OTP AEAD key", NULL, NULL}); register_subcommand(*c, (Command){"symmetric", yh_com_put_symmetric, "e:session,w:key_id,s:label,d:domains,c:" "capabilities,a:algorithm,i:key", fmt_hex, fmt_nofmt, "Store a symmetric key", NULL, NULL}); *c = register_command(*c, (Command){"quit", yh_com_quit, NULL, fmt_nofmt, fmt_nofmt, "Quit yubihsm-shell", NULL, NULL}); *c = register_command(*c, (Command){"exit", yh_com_quit, NULL, fmt_nofmt, fmt_nofmt, "Quit yubihsm-shell", NULL, NULL}); *c = register_command(*c, (Command){"session", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Manage sessions", NULL, NULL}); register_subcommand(*c, (Command){"close", yh_com_close_session, "e:session", fmt_nofmt, fmt_nofmt, "Close a session with a connector", NULL, NULL}); register_subcommand(*c, (Command){"open", yh_com_open_session, "w:authkey,i:password=-", fmt_password, fmt_nofmt, "Open a session with a device using a " "specific Authentication Key", NULL, NULL}); register_subcommand(*c, (Command){"open_asym", yh_com_open_session_asym, "w:authkey,i:privkey=-", fmt_PEM, fmt_nofmt, "Open a session with a device using a " "specific Asymmetric Authentication Key", NULL, NULL}); register_subcommand(*c, (Command){"ykopen", yh_com_open_yksession, "w:authkey,s:label,i:password=-,s:reader=", fmt_password, fmt_nofmt, "Open a session with a device using an " "Authentication in a YubiKey", NULL, NULL}); *c = register_command(*c, (Command){"sign", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Sign data", NULL, NULL}); register_subcommand( *c, (Command){"ecdsa", yh_com_sign_ecdsa, "e:session,w:key_id,a:algorithm,i:data=-,F:out=-", fmt_binary, fmt_base64, "Sign data using ECDSA", NULL, NULL}); register_subcommand( *c, (Command){"eddsa", yh_com_sign_eddsa, "e:session,w:key_id,a:algorithm,i:data=-,F:out=-", fmt_binary, fmt_base64, "Sign data using EDDSA", NULL, NULL}); register_subcommand( *c, (Command){"pkcs1v1_5", yh_com_sign_pkcs1v1_5, "e:session,w:key_id,a:algorithm,i:data=-,F:out=-", fmt_binary, fmt_base64, "Sign data using RSASSA-PKCS#1v1.5", NULL, NULL}); register_subcommand( *c, (Command){"pss", yh_com_sign_pss, "e:session,w:key_id,a:algorithm,i:data=-,F:out=-", fmt_binary, fmt_base64, "Sign data using RSASSA-PSS", NULL, NULL}); *c = register_command(*c, (Command){"hmac", yh_com_hmac, "e:session,w:key_id,i:data=-,F:out=-", fmt_hex, fmt_hex, "Hmac data", NULL, NULL}); *c = register_command(*c, (Command){"reset", yh_com_reset, "e:session", fmt_nofmt, fmt_nofmt, "Reset device", NULL, NULL}); *c = register_command(*c, (Command){"delete", yh_com_delete, "e:session,w:id,t:type", fmt_nofmt, fmt_nofmt, "Delete data", NULL, NULL}); *c = register_command(*c, (Command){"certify", yh_com_sign_ssh_certificate, "e:session,w:key_id,w:template_id,a:" "algorithm,i:infile=-,F:outfile=-", fmt_binary, fmt_binary, // TODO: correct default formats? "Sign SSH certificates", NULL, NULL}); *c = register_command(*c, (Command){"benchmark", yh_com_benchmark, "e:session,u:count,w:key_id=0,a:algorithm=any", fmt_nofmt, fmt_nofmt, "Run a set of benchmarks", NULL, NULL}); *c = register_command(*c, (Command){"otp", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "OTP commands", NULL, NULL}); register_subcommand(*c, (Command){"aead_create", yh_com_otp_aead_create, "e:session,w:key_id,i:key,i:private_id,F:aead", fmt_hex, fmt_binary, "Create an OTP AEAD", NULL, NULL}); register_subcommand(*c, (Command){"aead_random", yh_com_otp_aead_random, "e:session,w:key_id,F:aead", fmt_nofmt, fmt_binary, "Create a random OTP AEAD", NULL, NULL}); register_subcommand(*c, (Command){"decrypt", yh_com_otp_decrypt, "e:session,w:key_id,s:otp,i:aead", fmt_binary, fmt_nofmt, "Decrypt an OTP with AEAD", NULL, NULL}); register_subcommand( *c, (Command){"rewrap", yh_com_otp_rewrap, "e:session,w:id_from,w:id_to,i:aead_in,F:aead_out", fmt_binary, fmt_binary, "Rewrap an OTP aead to a different key", NULL, NULL}); *c = register_command(*c, (Command){"attest", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Attest device objects", NULL, NULL}); register_subcommand(*c, (Command){"asymmetric", yh_com_sign_attestation_certificate, "e:session,w:key_id,w:attest_id=0,F:file=-", fmt_nofmt, fmt_PEM, "Sign attestation certificate", NULL, NULL}); *c = register_command(*c, (Command){"keepalive", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Change keepalive settings", NULL, NULL}); register_subcommand(*c, (Command){"on", yh_com_keepalive_on, NULL, fmt_nofmt, fmt_nofmt, "Enable keepalive", NULL, NULL}); register_subcommand(*c, (Command){"off", yh_com_keepalive_off, NULL, fmt_nofmt, fmt_nofmt, "Disable keepalive", NULL, NULL}); *c = register_command(*c, (Command){"set", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Set preferences", NULL, NULL}); register_subcommand(*c, (Command){"informat", yh_com_set_informat, "I:format", fmt_nofmt, fmt_nofmt, "Set input format", NULL, NULL}); register_subcommand(*c, (Command){"outformat", yh_com_set_outformat, "I:format", fmt_nofmt, fmt_nofmt, "Set output format", NULL, NULL}); register_subcommand(*c, (Command){"cacert", yh_com_set_cacert, "s:file", fmt_nofmt, fmt_nofmt, "Set CA cert to use for https to connector", NULL, NULL}); register_subcommand(*c, (Command){"cert", yh_com_set_cert, "s:file", fmt_nofmt, fmt_nofmt, "Set client cert to use for https to connector", NULL, NULL}); register_subcommand(*c, (Command){"key", yh_com_set_key, "s:file", fmt_nofmt, fmt_nofmt, "Set client key to use for https to connector", NULL, NULL}); register_subcommand(*c, (Command){"proxy", yh_com_set_proxy, "s:proxy", fmt_nofmt, fmt_nofmt, "Set proxyserver to use for connector", NULL, NULL}); register_subcommand(*c, (Command){"noproxy", yh_com_set_noproxy, "s:noproxy", fmt_nofmt, fmt_nofmt, "Set noproxy list to use for connector", NULL, NULL}); *c = register_command(*c, (Command){"blink", yh_com_blink, "e:session,b:seconds=10", fmt_nofmt, fmt_nofmt, "Blink the device", NULL, NULL}); *c = register_command(*c, (Command){"change", yh_com_noop, NULL, fmt_nofmt, fmt_nofmt, "Change objects", NULL, NULL}); register_subcommand(*c, (Command){"authkey", yh_com_change_authentication_key, "e:session,w:key_id,i:password=-", fmt_password, fmt_nofmt, "Change an authentication key", NULL, NULL}); register_subcommand(*c, (Command){"authkey_asym", yh_com_change_authentication_key_asym, "e:session,w:key_id,i:pubkey=-", fmt_PEM, fmt_nofmt, "Change an asymmetric authentication key", NULL, NULL}); *c = msort_list(*c); for (Command *t = *c; t != NULL; t = t->next) { if (t->subcommands != NULL) { t->subcommands = msort_list(t->subcommands); } } } // NOTE(adma): the prototype for el functions is fixed, no way to pass // in parameters, we must use globals CommandList g_commands; static bool g_running = true; static cmd_format g_in_fmt, g_out_fmt; // NOTE(adma): Print the command history // argc = 0 int yh_com_history(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); UNUSED(ctx); UNUSED(argv); #ifndef __WIN32 HistEvent ev; int rv; for (rv = history(g_hist, &ev, H_LAST); rv != -1; rv = history(g_hist, &ev, H_PREV)) { fprintf(ctx->out, "%4d %s", ev.num, ev.str); } #endif return 0; } static const char *fmt_to_string(cmd_format fmt) { for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { if (formats[i].format == fmt) { return formats[i].name; } } return "No format"; } // NOTE(adma): Print information about a command // argc = 1 // arg 0: s:command int yh_com_help(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); UNUSED(ctx); bool match = false; // TODO(adma): once we have optional commands we can have a real help for (Command *command = g_commands; command; command = command->next) { if (strncmp(argv[0].s, command->name, strlen(argv[0].s)) == 0) { match = true; printf("%-25s%s\n", command->name, command->doc); if (strlen(argv[0].s)) { if (command->args) { printf("%-5s%s", "", command->args); if (command->in_fmt != fmt_nofmt) { printf(" (default input format: %s)", fmt_to_string(command->in_fmt)); } printf("\n"); } for (Command *subcommand = command->subcommands; subcommand; subcommand = subcommand->next) { printf("%-5s%-25s%s", "", subcommand->name, subcommand->doc); if (subcommand->args) { if (subcommand->in_fmt != fmt_nofmt) { printf(" (default input format: %s)", fmt_to_string(subcommand->in_fmt)); } printf("\n%-30s%s\n", "", subcommand->args); } else { printf("\n"); } } } } } if (match == false) { printf("Help for command %s not found\n", argv[0].s); } return 0; } // NOTE(adma): Quit // argc = 0 int yh_com_quit(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); UNUSED(ctx); UNUSED(argv); g_running = false; return 0; } static bool probe_session(yubihsm_context *ctx, size_t index) { if (ctx->sessions[index]) { uint8_t data = 0xff; uint8_t response[YH_MSG_BUF_SIZE]; size_t response_len = sizeof(response); yh_cmd response_cmd; yh_rc yrc; // silently ignore transmit errors..? if ((yrc = yh_send_secure_msg(ctx->sessions[index], YHC_ECHO, &data, 1, &response_cmd, response, &response_len)) != YHR_SUCCESS) { yh_destroy_session(&ctx->sessions[index]); fprintf(stderr, "Failed to probe session %zu: %s\n", index, yh_strerror(yrc)); return false; } return true; } else { return false; } } #ifdef __WIN32 static void WINAPI timer_handler(void *lpParam, unsigned char TimerOrWaitFired) { UNUSED(TimerOrWaitFired); #else static void timer_handler(int signo __attribute__((unused))) { #endif if (calling_device == true || g_ctx.connector == NULL) { return; } for (size_t i = 0; i < sizeof(g_ctx.sessions) / sizeof(g_ctx.sessions[0]); i++) { probe_session(&g_ctx, i); } } static int set_keepalive(uint16_t seconds) { #ifdef __WIN32 HANDLE timer; static HANDLE timerQueue = NULL; if (timerQueue != NULL) { DeleteTimerQueue(timerQueue); } timerQueue = CreateTimerQueue(); if (timerQueue == NULL) { fprintf(stderr, "Failed to setup timer\n"); return 1; } CreateTimerQueueTimer(&timer, timerQueue, timer_handler, NULL, seconds * 1000, seconds * 1000, 0); if (timer == NULL) { fprintf(stderr, "Failed to start time\n"); return 1; } #else struct itimerval itimer; itimer.it_interval.tv_sec = seconds; itimer.it_interval.tv_usec = 0; itimer.it_value.tv_sec = seconds; itimer.it_value.tv_usec = 0; if (setitimer(ITIMER_REAL, &itimer, NULL) != 0) { fprintf(stderr, "Failed to setup timer\n"); return 1; } #endif fprintf(stderr, "Session keepalive set up to run every %d seconds\n", seconds); return 0; } // NOTE: Enable keepalive // argc = 0 int yh_com_keepalive_on(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); return set_keepalive(15); } // NOTE: Disable keepalive // argc = 0 int yh_com_keepalive_off(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); return set_keepalive(0); } int yh_com_set_informat(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { if (strcasecmp(argv[0].s, formats[i].name) == 0) { g_in_fmt = formats[i].format; return 0; } } fprintf(stderr, "Failed to parse input format\n"); return -1; } int yh_com_set_outformat(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { if (strcasecmp(argv[0].s, formats[i].name) == 0) { if (formats[i].format == fmt_password) { break; } g_out_fmt = formats[i].format; return 0; } } fprintf(stderr, "Failed to parse output format\n"); return -1; } static void find_lcp(const char *items[], int n_items, const char **lcp, int *lcp_len) { int min = 0; int max = 0; if (items == NULL || n_items == 0) { *lcp = NULL; *lcp_len = 0; } for (int i = 1; i < n_items; i++) { if (strcmp(items[i], items[min]) < 0) { min = i; } else if (strcmp(items[i], items[max]) > 0) { max = i; } } *lcp = items[min]; for (size_t i = 0; i < strlen(items[min]) && i < strlen(items[max]); i++) { if (items[min][i] != items[max][i]) { *lcp_len = i; return; } } *lcp_len = strlen(items[min]); } static int tokenize(char *line, char **toks, int max_toks, int *cursorc, int *cursoro, const char *space) { int i; int tok = 0; int length = strlen(line); int start_of_word = 0; enum states { WHITESPACE, WORD, QUOTE } state = WHITESPACE; toks[0] = line; // set up as fall-through for (i = 0; i <= length; i++) { char c = line[i]; if (cursorc && i == *cursorc && tok > 0) { if (state == WHITESPACE) { *cursoro = 0; *cursorc = tok; } else { *cursoro = i - start_of_word; *cursorc = tok - 1; } } if (c == '\0') { break; } if (tok >= max_toks) { return -1; } switch (state) { case WHITESPACE: { bool found = false; for (size_t j = 0; j < strlen(space); j++) { if (c == space[j]) { found = true; break; } } if (found) { break; } if (c == '"') { state = QUOTE; start_of_word = i + 1; } else if (c == '#') { return tok; } else { state = WORD; start_of_word = i; } toks[tok++] = line + start_of_word; } break; case QUOTE: if (c == '"') { line[i] = '\0'; state = WHITESPACE; } break; case WORD: for (size_t j = 0; j < strlen(space); j++) { if (c == space[j]) { line[i] = '\0'; state = WHITESPACE; } } break; } } return tok; } #ifndef __WIN32 static int compare_strings(const void *a, const void *b) { return strcmp(*(char *const *) a, *(char *const *) b); } static unsigned char complete_arg(EditLine *el, const char *arg, char *line, int cursoro) { const char *candidates[COMPLETION_CANDIDATES]; int n_candidates = 0; struct winsize w; const LineInfo *li = el_line(el); ioctl(fileno(stdout), TIOCGWINSZ, &w); int lines = (li->cursor - li->buffer + strlen(PROMPT)) / w.ws_col; switch (arg[0]) { case 'u': printf("\nnumber"); break; case 'w': printf("\nword"); break; case 'b': printf("\nbyte"); break; case 'i': printf("\ninput data"); break; case 'F': printf("\noutput filename"); break; case 's': printf("\nstring"); break; case 'k': printf("\nkey"); break; case 'e': printf("\nsession"); break; case 'd': printf("\ndomains"); break; case 'c': { char *toks[COMPLETION_CANDIDATES]; int cursorc = cursoro; int num_toks = tokenize(line, toks, COMPLETION_CANDIDATES, &cursorc, &cursoro, ":,;|"); if (cursorc == num_toks) { toks[cursorc] = ""; } for (size_t i = 0; i < sizeof(yh_capability) / sizeof(yh_capability[0]); i++) { if (strncasecmp(toks[cursorc], yh_capability[i].name, strlen(toks[cursorc])) == 0) { candidates[n_candidates++] = yh_capability[i].name; assert(n_candidates < COMPLETION_CANDIDATES); } } } break; case 'a': for (size_t i = 0; i < sizeof(yh_algorithms) / sizeof(yh_algorithms[0]); i++) { if (strncasecmp(line, yh_algorithms[i].name, strlen(line)) == 0) { candidates[n_candidates++] = yh_algorithms[i].name; assert(n_candidates < COMPLETION_CANDIDATES); } } break; case 't': for (size_t i = 0; i < sizeof(yh_types) / sizeof(yh_types[0]); i++) { if (strncasecmp(line, yh_types[i].name, strlen(line)) == 0) { candidates[n_candidates++] = yh_types[i].name; assert(n_candidates < COMPLETION_CANDIDATES); } } break; case 'o': for (size_t i = 0; i < sizeof(yh_options) / sizeof(yh_options[0]); i++) { if (strncasecmp(line, yh_options[i].name, strlen(line)) == 0) { candidates[n_candidates++] = yh_options[i].name; assert(n_candidates < COMPLETION_CANDIDATES); } } break; case 'I': for (size_t i = 0; i < sizeof(formats) / sizeof(formats[0]); i++) { if (strncasecmp(line, formats[i].name, strlen(line)) == 0) { candidates[n_candidates++] = formats[i].name; assert(n_candidates < COMPLETION_CANDIDATES); } } break; case '\0': // NOTE(adma): completing an empty string, we reached the end, do // nothing return CC_ERROR; default: printf("\nunknown type"); break; } switch (n_candidates) { case 0: { int i = 1; while (arg[i] != '\0' && arg[i] != ',') { i++; } printf("%*.*s\n", i, i - 1, arg + 1); } break; case 1: el_insertstr(el, candidates[0] + cursoro); return CC_REDISPLAY; default: { const char *lcp; int lcp_len; qsort(candidates, n_candidates, sizeof(char *), compare_strings); find_lcp(candidates, n_candidates, &lcp, &lcp_len); if (cursoro == lcp_len) { // NOTE(adma): we already have lcp_len characters typed on // the prompt, display all the possible matches printf("\n"); for (int i = 0; i < n_candidates; i++) { printf("%s\n", candidates[i]); } } else { // NOTE(adma): we found an lcp, autocomplete with that char prefix[MAX_COMMAND_NAME]; strcpy(prefix, lcp + cursoro); prefix[lcp_len - cursoro] = '\0'; el_insertstr(el, prefix); return CC_REDISPLAY; } } } for (int i = 0; i < lines; i++) { printf("\n"); } return CC_REDISPLAY; } static unsigned char complete_command(EditLine *el, Command *to_complete, const char *line, int cursoro) { const char *candidates[COMPLETION_CANDIDATES]; int n_candidates = 0; // NOTE(adma): try to autocomplete the current command/subcomand for (Command *command = to_complete; command; command = command->next) { if (strncmp(line, command->name, strlen(line)) == 0) { // printf("%s\n", command->name); candidates[n_candidates++] = command->name; assert(n_candidates < COMPLETION_CANDIDATES); } else if (n_candidates != 0) { // NOTE(adma): the list is sorted no point in continuing, // bail out break; } } // printf("Found %d candidates\n", n_candidates); switch (n_candidates) { case 0: // NOTE(adma): no matches, do nothing return CC_ERROR; case 1: // NOTE(adma): only one match, autocomplete! el_insertstr(el, candidates[0] + cursoro); el_insertstr(el, " "); return CC_REDISPLAY; default: { // NOTE(adma): several matches, find longest common prefix const char *lcp; int lcp_len; find_lcp(candidates, n_candidates, &lcp, &lcp_len); if (cursoro == lcp_len) { // NOTE(adma): we already have lcp_len characters typed on // the prompt, display all the possible matches printf("\n"); for (int i = 0; i < n_candidates; i++) { printf("%s\n", candidates[i]); } } else { // NOTE(adma): we found an lcp, autocomplete with that char prefix[MAX_COMMAND_NAME]; strcpy(prefix, lcp + cursoro); prefix[lcp_len - cursoro] = '\0'; el_insertstr(el, prefix); } } return CC_REDISPLAY; } } static unsigned char yubihsm_complete(EditLine *el, int ch) { UNUSED(ch); const LineInfo *li; int argc, cursorc = 0, cursoro = 0; char *argv[64]; char data[ARGS_BUFFER_SIZE + 1] = {0}; li = el_line(el); cursorc = li->cursor - li->buffer; if (li->lastchar - li->buffer > 1024) { return CC_REDISPLAY; } memcpy(data, li->buffer, li->lastchar - li->buffer); argc = tokenize(data, argv, 64, &cursorc, &cursoro, SPACES); // printf("\nargc %d, cursorc: %d, cursoro: %d\n", argc, cursorc, cursoro); if (argc == 0) { // NOTE(adma): no prompt, don't even bother with finding a match, // just show all commands, one per line printf("\n"); for (Command *command = g_commands; command; command = command->next) { printf("%s\n", command->name); } return CC_REDISPLAY; } else { int i = 0; Command *command = g_commands; Command *to_complete = NULL; char *args = ""; bool completing_args = false; while (i < cursorc) { // NOTE(adma): match the first n-1 items if (completing_args == false) { // NOTE(adma): match subcommands if (strncmp(argv[i], command->name, strlen(argv[i])) == 0) { // printf("\nmatched %s\n", command->name); to_complete = command; // to_complete_position = i; if (command->subcommands != NULL) { // NOTE(adma): if we were matching subcommands, keep // matching subcommands if any command = command->subcommands; } else { // NOTE(adma): start matching arguments otherwise completing_args = true; if (command->args != NULL) { args = command->args; } else { // NOTE(adma): there are no args for this command break; } } i++; // NOTE(adma): next word } else { command = command->next; if (command == NULL) { // NOTE(adma): command not found break; } } } else { // NOTE(adma): match arguments while (*args != '\0' && *args != ',') { args++; } if (*args == ',') { args++; i++; // NOTE(adma): next word } else { break; } } } if (to_complete && cursorc != 0) { // NOTE(adma): 0 has a bit of a special meaning since the cursor // is after the last letter of the first word and we still want // to autocomplete commands and not subcommands nor args in that // case to_complete = to_complete->subcommands; } if (argc == cursorc) { if (to_complete && completing_args == false) { // NOTE(adma): cursor is after a command but there is no more // text to match, show all subcommands printf("\n"); for (Command *iter = to_complete; iter; iter = iter->next) { printf("%s\n", iter->name); } return CC_REDISPLAY; } else { // NOTE(adma): or show the current argument return complete_arg(el, args, "", 0); } } else { if (completing_args == false) { if (to_complete == NULL) { to_complete = g_commands; } return complete_command(el, to_complete, argv[i], cursoro); } else { return complete_arg(el, args, argv[i], cursoro); } } } return CC_ERROR; } static char *prompt(EditLine *el) { UNUSED(el); return PROMPT; } #else char *converting_fgets(char *s, int size, FILE *stream) { int translation = _setmode(_fileno(stream), _O_U16TEXT); if (translation == -1) { return NULL; } wchar_t *wide_str = calloc(size, sizeof(wchar_t)); if (wide_str == NULL) { _setmode(_fileno(stream), translation); return NULL; } fgetws(wide_str, sizeof(wchar_t) * size, stream); int len = WideCharToMultiByte(CP_UTF8, 0, wide_str, -1, s, size, NULL, NULL); free(wide_str); wide_str = NULL; _setmode(_fileno(stream), translation); if (len == 0) { return NULL; } return s; } #endif static FILE *open_file(const char *name, bool input) { if (input) { if (strcmp(name, "-") == 0) { return stdin; } else { return fopen(name, "rb"); } } else { if (strcmp(name, "-") == 0) { return stdout; } else { return fopen(name, "ab"); } } } static bool get_input_data(const char *name, uint8_t **out, size_t *len, cmd_format fmt) { const char *fname = strncasecmp(name, "file:", 5) ? name : name + 5; struct stat sb = {0}; int st_res = stat(fname, &sb); if (st_res == 0 && S_ISREG(sb.st_mode)) { *len = sb.st_size; } else { *len = ARGS_BUFFER_SIZE; } *out = calloc(*len + 1, 1); if (*out == 0) { fprintf(stderr, "Failed to allocate %zu bytes memory for %s\n", *len, fname); return false; } if (!strcmp(name, "-") || fname != name || (st_res == 0 && S_ISREG(sb.st_mode))) { bool ret = false; FILE *file = open_file(fname, true); if (!file) { return false; } if (file == stdin && fmt == fmt_password) { #ifndef __WIN32 // NOTE: we have to stop the timer around the call to // EVP_read_pw_string(), openssl gets sad if a signal hits while waiting // for input from the user. So we stop the timer and restore it when we're // done struct itimerval stoptimer, oldtimer; memset(&stoptimer, 0, sizeof(stoptimer)); if (setitimer(ITIMER_REAL, &stoptimer, &oldtimer) != 0) { fprintf(stderr, "Failed to setup timer\n"); return false; } #endif if (EVP_read_pw_string((char *) *out, *len - 1, "Enter password: ", 0) == 0) { *len = strlen((char *) *out); ret = true; } #ifndef __WIN32 if (setitimer(ITIMER_REAL, &oldtimer, NULL) != 0) { fprintf(stderr, "Failed to restore timer\n"); return false; } #endif } else if (read_file(file, *out, len)) { ret = true; } if (file != stdin) { fclose(file); } if (ret == false) { return ret; } } else { if (strlen(name) < *len) { memcpy(*out, name, strlen(name)); *len = strlen(name); } else { return false; } } switch (fmt) { case fmt_base64: if (base64_decode((char *) *out, *out, len)) { return true; } break; case fmt_hex: if (hex_decode((char *) *out, *out, len)) { return true; } break; case fmt_password: // If the password was read from a file, strip off \r\n if (*len > 0 && (*out)[*len - 1] == '\n') { (*len)--; } if (*len > 0 && (*out)[*len - 1] == '\r') { (*len)--; } (*out)[*len] = '\0'; return true; case fmt_binary: // these all require no extra work, just pass data on. case fmt_PEM: case fmt_ASCII: return true; case fmt_nofmt: default: return false; } return false; } static int validate_arg(yubihsm_context *ctx, char type, const char *value, Argument *parsed, cmd_format fmt) { switch (type) { case 'b': // byte case 'w': // word case 'e': // session case 'u': { // unsigned long uint32_t max = 0; if (type == 'b') { max = UCHAR_MAX; } else if (type == 'w' || type == 'e') { max = USHRT_MAX; } else if (type == 'u') { max = UINT_MAX; } // NOTE(adma): check that is a positive number in dec, hex or oct errno = 0; char *endptr; unsigned long num = strtoul(value, &endptr, 0); if ((errno == ERANGE || num > max) || (errno != 0 && num == 0)) { return -1; } if (endptr == value) { return -1; } if (type == 'b') { parsed->b = (uint8_t) num; } else if (type == 'e') { if (num >= sizeof(ctx->sessions) / sizeof(ctx->sessions[0]) || !probe_session(ctx, num)) { return -1; } parsed->e = ctx->sessions[num]; } else if (type == 'w') { parsed->w = (uint16_t) num; } else if (type == 'u') { parsed->d = (uint32_t) num; } parsed->len = 1; // NOTE(adma): doesn't really have a meaning } break; case 'F': parsed->s = value; parsed->len = strlen(value); ctx->out = open_file(value, false); if (!ctx->out) { return -1; } break; case 'i': if (get_input_data(value, &parsed->x, &parsed->len, fmt) == false) { return -1; } break; case 'I': case 's': // NOTE(adma): strings are pretty much always OK parsed->s = value; parsed->len = strlen(value); break; case 'd': if (yh_string_to_domains(value, &parsed->w) != YHR_SUCCESS) { return -1; } break; case 'c': if (yh_string_to_capabilities(value, &parsed->c) != YHR_SUCCESS) { return -1; } break; case 'a': if (yh_string_to_algo(value, &parsed->a) != YHR_SUCCESS) { return -1; } break; case 't': if (yh_string_to_type(value, &parsed->t) != YHR_SUCCESS) { return -1; } break; case 'o': if (yh_string_to_option(value, &parsed->o) != YHR_SUCCESS) { return -1; } break; default: // NOTE(adma): unknown type return -1; } return 0; } static int validate_and_call(yubihsm_context *ctx, CommandList l, const char *line) { int argc = 0; char *argv[64]; int i = 0; char data[ARGS_BUFFER_SIZE + 1]; char arg_data[ARGS_BUFFER_SIZE + 1] = {0}; Command *command = l; bool completing_args = false; const char *args = ""; Argument arguments[MAX_ARGUMENTS] = {{{0}, 0, 0}}; int n_arguments = 0; bool invalid_arg = false; int match; bool found = false; CommandFunction *func = NULL; memset(data, 0x0, sizeof(data)); memset(arg_data, 0x0, sizeof(data)); if (strlen(line) > ARGS_BUFFER_SIZE) { printf("Command too long\n"); return 0; } strcpy(data, line); argc = tokenize(data, argv, 64, NULL, NULL, SPACES); while (i < argc) { // NOTE(adma): match the first n-1 items if (completing_args == false) { // NOTE(adma): match subcommands match = strncmp(argv[i], command->name, strlen(argv[i])); if (match == 0) { if (command->subcommands != NULL) { // NOTE(adma): if we were matching subcommands, keep // matching subcommands if any command = command->subcommands; } else { // NOTE(adma): start matching arguments otherwise. Also keep // track of the function because that's the one we want to // call later on completing_args = true; func = command->func; if (command->args != NULL) { char *arg_toks[64]; args = command->args; strncpy(arg_data, args, ARGS_BUFFER_SIZE); // since tokenize() modifies the buffer.. int num_args = tokenize(arg_data, arg_toks, 64, NULL, NULL, ","); if (num_args + 1 + i != argc) { // some arguments might have default values for (int j = 0; j < num_args; j++) { if (j < argc - 1 - i) { continue; } char *str = strchr(arg_toks[j], '='); if (str == NULL) { break; } str++; argv[j + 1 + i] = str; argc++; } } } else { // NOTE(adma): there are no args for this command found = true; break; } } i++; // NOTE(adma): next word } else { // NOTE(adma): command not found command = command->next; if (match < 0 || command == NULL) { command = NULL; break; } } } else { // NOTE(adma): match arguments if (validate_arg(ctx, *args, argv[i], arguments + n_arguments++, g_in_fmt != fmt_nofmt ? g_in_fmt : command->in_fmt) != 0) { invalid_arg = true; break; } while (*args != '\0' && *args != ',') { args++; } if (*args == ',') { args++; i++; // NOTE(adma): next word } else { found = true; break; } } } if (found == true) { calling_device = true; func(ctx, arguments, g_in_fmt == fmt_nofmt ? command->in_fmt : g_in_fmt, g_out_fmt == fmt_nofmt ? command->out_fmt : g_out_fmt); calling_device = false; for (i = 0; i < n_arguments; i++) { if (arguments[i].x != NULL) { free(arguments[i].x); arguments[i].x = NULL; } } // NOTE: if ctx->in or ctx->out is changed, close and return state, // otherwise the next command that needs a file might get sad. if (ctx->out != stdout) { fclose(ctx->out); ctx->out = stdout; } } else { if (invalid_arg == true) { char arg[ARGS_BUFFER_SIZE + 1]; memset(arg, 0x0, sizeof(arg)); strncpy(arg, args, ARGS_BUFFER_SIZE); char *end = strchr(args, ','); if (end) { arg[end - args] = '\0'; } printf("Invalid argument %d: %s (%s)\n", i, argv[i], arg); } else if (command == NULL) { printf("Command %s%s%s not found\n", argv[0], i ? " " : "", i ? argv[1] : ""); } else if (*args != '\0' || argc - 1 == 0) { printf("Incomplete command\n"); for (i = 0; i < argc; i++) { arguments[i].s = argv[i]; } yh_com_help(NULL, arguments, fmt_nofmt, fmt_nofmt); } } return 0; } static void free_configured_connectors(yubihsm_context *ctx) { if (ctx->connector_list) { for (int i = 0; ctx->connector_list[i]; i++) { free(ctx->connector_list[i]); } free(ctx->connector_list); ctx->connector_list = NULL; } } static int parse_configured_connectors(yubihsm_context *ctx, char **connectors, int n_connectors) { ctx->connector_list = calloc(n_connectors + 1, sizeof(char *)); if (ctx->connector_list == NULL) { return -1; } for (int i = 0; i < n_connectors; i++) { ctx->connector_list[i] = strdup(connectors[i]); if (ctx->connector_list[i] == NULL) { free_configured_connectors(ctx); return -1; } } return 0; } static void free_configured_pubkeys(yubihsm_context *ctx) { if (ctx->device_pubkey_list) { for (int i = 0; ctx->device_pubkey_list[i]; i++) { free(ctx->device_pubkey_list[i]); } free(ctx->device_pubkey_list); ctx->device_pubkey_list = NULL; } } static int parse_configured_pubkeys(yubihsm_context *ctx, char **pubkeys, int n_pubkeys) { ctx->device_pubkey_list = calloc(n_pubkeys + 1, sizeof(uint8_t *)); if (ctx->device_pubkey_list == NULL) return -1; for (int i = 0; i < n_pubkeys; i++) { uint8_t pk[80]; size_t pk_len = sizeof(pk); hex_decode(pubkeys[i], pk, &pk_len); if (pk_len == YH_EC_P256_PUBKEY_LEN) { ctx->device_pubkey_list[i] = malloc(pk_len); } if (ctx->device_pubkey_list[i]) { memcpy(ctx->device_pubkey_list[i], pk, pk_len); } else { free_configured_pubkeys(ctx); return -1; } } return 0; } int main(int argc, char *argv[]) { yh_rc yrc; int comrc; int rc = EXIT_SUCCESS; struct gengetopt_args_info args_info; struct stat sb; struct cmdline_parser_params params; if (setlocale(LC_ALL, "") == NULL) { fprintf(stderr, "Warning, unable to reset locale\n"); } g_ctx.out = stdout; cmdline_parser_params_init(¶ms); params.initialize = 1; params.check_required = 0; if (cmdline_parser(argc, argv, &args_info) != 0) { return EXIT_FAILURE; } if (stat(args_info.config_file_arg, &sb) == 0) { if (S_ISREG(sb.st_mode) || S_ISLNK(sb.st_mode)) { params.initialize = 0; if (cmdline_parser_config_file(args_info.config_file_arg, &args_info, ¶ms) != 0) { return EXIT_FAILURE; } } } if (cmdline_parser_required(&args_info, argv[0]) != 0) { return EXIT_FAILURE; } switch (args_info.informat_arg) { case informat_arg_base64: g_in_fmt = fmt_base64; break; case informat_arg_binary: g_in_fmt = fmt_binary; break; case informat_arg_PEM: g_in_fmt = fmt_PEM; break; case informat_arg_password: g_in_fmt = fmt_password; break; case informat_arg_hex: g_in_fmt = fmt_hex; break; case informat__NULL: case informat_arg_default: default: g_in_fmt = fmt_nofmt; break; } switch (args_info.outformat_arg) { case outformat_arg_base64: g_out_fmt = fmt_base64; break; case outformat_arg_binary: g_out_fmt = fmt_binary; break; case outformat_arg_PEM: g_out_fmt = fmt_PEM; break; case outformat_arg_hex: g_out_fmt = fmt_hex; break; case outformat__NULL: case outformat_arg_default: default: g_out_fmt = fmt_nofmt; break; } if (parse_configured_connectors(&g_ctx, args_info.connector_arg, args_info.connector_given) == -1) { fprintf(stderr, "Unable to parse connector list\n"); rc = EXIT_FAILURE; goto main_exit; } if (parse_configured_pubkeys(&g_ctx, args_info.device_pubkey_arg, args_info.device_pubkey_given) == -1) { fprintf(stderr, "Unable to parse device pubkey list\n"); rc = EXIT_FAILURE; goto main_exit; } if (getenv("DEBUG") != NULL) { args_info.verbose_arg = YH_VERB_ALL; } yh_set_verbosity(g_ctx.connector, args_info.verbose_arg); yrc = yh_init(); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to initialize libyubihsm\n"); rc = EXIT_FAILURE; goto main_exit; } ykhsmauth_rc ykhsmauthrc; ykhsmauthrc = ykhsmauth_init(&g_ctx.state, 1); // TODO(adma): do something about verbosity if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Failed to initialize libykhsmauth\n"); rc = EXIT_FAILURE; goto main_exit; } if (g_ctx.connector_list[0] == NULL) { fprintf(stderr, "Using default connector URL: %s\n", DEFAULT_CONNECTOR_URL); char *default_connector_url = DEFAULT_CONNECTOR_URL; free_configured_connectors(&g_ctx); parse_configured_connectors(&g_ctx, &default_connector_url, 1); } if (args_info.cacert_given) { g_ctx.cacert = strdup(args_info.cacert_arg); } if (args_info.cert_given) { g_ctx.cert = strdup(args_info.cert_arg); } if (args_info.key_given) { g_ctx.key = strdup(args_info.key_arg); } if (args_info.proxy_given) { g_ctx.proxy = strdup(args_info.proxy_arg); } if (args_info.noproxy_given) { g_ctx.noproxy = strdup(args_info.noproxy_arg); } #ifndef __WIN32 struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = timer_handler; act.sa_flags = SA_RESTART; sigaction(SIGALRM, &act, NULL); sigset_t set; sigemptyset(&set); sigaddset(&set, SIGALRM); sigprocmask(SIG_UNBLOCK, &set, NULL); #endif if (args_info.action_given) { g_ctx.out = open_file(args_info.out_arg, false); if (g_ctx.out == NULL) { fprintf(stderr, "Unable to open output file %s\n", args_info.out_arg); rc = EXIT_FAILURE; goto main_exit; } yh_com_connect(&g_ctx, NULL, fmt_nofmt, fmt_nofmt); bool requires_session = false; for (unsigned i = 0; i < args_info.action_given; i++) { switch (args_info.action_arg[i]) { case action_arg_getMINUS_deviceMINUS_info: case action_arg_getMINUS_deviceMINUS_pubkey: requires_session = false; break; default: requires_session = true; } if (requires_session == true) { break; } } Argument arg[11] = {0}; if (requires_session == true) { uint8_t *buf = 0; size_t pw_len = 0; arg[0].w = args_info.authkey_arg; if (get_input_data(args_info.password_given ? args_info.password_arg : "-", &buf, &pw_len, fmt_password) == false) { fprintf(stderr, "Failed to get password\n"); rc = EXIT_FAILURE; goto main_exit; } if (args_info.ykhsmauth_label_given) { arg[1].s = args_info.ykhsmauth_label_arg; arg[1].len = strlen(args_info.ykhsmauth_label_arg); arg[2].x = buf; arg[2].len = pw_len; arg[3].s = args_info.ykhsmauth_reader_arg; arg[3].len = strlen(args_info.ykhsmauth_reader_arg); comrc = yh_com_open_yksession(&g_ctx, arg, fmt_password, fmt_nofmt); } else { arg[1].x = buf; arg[1].len = pw_len; comrc = yh_com_open_session(&g_ctx, arg, fmt_password, fmt_nofmt); } insecure_memzero(buf, pw_len); free(buf); if (comrc != 0) { fprintf(stderr, "Failed to open session\n"); rc = EXIT_FAILURE; goto main_exit; } } for (size_t i = 0; i < sizeof(g_ctx.sessions) / sizeof(g_ctx.sessions[0]); i++) { if (g_ctx.sessions[i] != NULL) { arg[0].e = g_ctx.sessions[i]; break; } } calling_device = true; for (unsigned i = 0; i < args_info.action_given; i++) { switch (args_info.action_arg[i]) { case action_arg_decryptMINUS_pkcs1v15: { arg[1].w = args_info.object_id_arg; if (get_input_data(args_info.in_arg, &arg[2].x, &arg[2].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_decrypt_pkcs1v1_5(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); free(arg[2].x); COM_SUCCEED_OR_DIE(comrc, "Unable to decrypt data"); } break; case action_arg_deriveMINUS_ecdh: { arg[1].w = args_info.object_id_arg; if (get_input_data(args_info.in_arg, &arg[2].x, &arg[2].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_derive_ecdh(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_hex : g_out_fmt); free(arg[2].x); COM_SUCCEED_OR_DIE(comrc, "Unable to perform ECDH key exchange"); } break; case action_arg_decryptMINUS_oaep: case action_arg_decryptMINUS_aesccm: case action_arg_encryptMINUS_aesccm: LIB_SUCCEED_OR_DIE(YHR_GENERIC_ERROR, "Command not implemented: "); case action_arg_encryptMINUS_aescbc: case action_arg_decryptMINUS_aescbc: { if (args_info.iv_given == 0) { fprintf(stderr, "Missing argument IV\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.iv_arg; if (get_input_data(args_info.in_arg, &arg[3].x, &arg[3].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } if (args_info.action_arg[i] == action_arg_encryptMINUS_aescbc) { comrc = yh_com_encrypt_aes_cbc(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); free(arg[3].x); COM_SUCCEED_OR_DIE(comrc, "Unable to encrypt input"); } else { comrc = yh_com_decrypt_aes_cbc(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); free(arg[3].x); COM_SUCCEED_OR_DIE(comrc, "Unable to decrypt input"); } } break; case action_arg_encryptMINUS_aesecb: case action_arg_decryptMINUS_aesecb: { arg[1].w = args_info.object_id_arg; if (get_input_data(args_info.in_arg, &arg[2].x, &arg[2].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } if (args_info.action_arg[i] == action_arg_encryptMINUS_aesecb) { comrc = yh_com_encrypt_aes_ecb(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); free(arg[2].x); COM_SUCCEED_OR_DIE(comrc, "Unable to encrypt input"); } else { comrc = yh_com_decrypt_aes_ecb(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); free(arg[2].x); COM_SUCCEED_OR_DIE(comrc, "Unable to decrypt input"); } } break; case action_arg_generateMINUS_asymmetricMINUS_key: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); comrc = yh_com_generate_asymmetric(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to generate asymmetric key"); } break; case action_arg_generateMINUS_hmacMINUS_key: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); comrc = yh_com_generate_hmac(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to generate hmac key"); } break; case action_arg_generateMINUS_wrapMINUS_key: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } if (args_info.delegated_given == 0) { fprintf(stderr, "Missing delegated capabilities\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); memset(&arg[5].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.delegated_arg, &arg[5].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[6].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); comrc = yh_com_generate_wrap(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to generate wrap key"); } break; case action_arg_generateMINUS_otpMINUS_aeadMINUS_key: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } if (args_info.nonce_given == 0) { fprintf(stderr, "Missing argument nonce\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); arg[6].d = args_info.nonce_arg; comrc = yh_com_generate_otp_aead_key(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to generate otp key"); } break; case action_arg_generateMINUS_symmetricMINUS_key: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); comrc = yh_com_generate_symmetric(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to generate symmetric key"); } break; case action_arg_getMINUS_opaque: { arg[1].w = args_info.object_id_arg; comrc = yh_com_get_opaque(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get opaque object"); } break; case action_arg_getMINUS_pseudoMINUS_random: { arg[1].w = args_info.count_arg; comrc = yh_com_get_random(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_hex : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get random bytes"); } break; case action_arg_getMINUS_storageMINUS_info: comrc = yh_com_get_storage(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get storage stats"); break; case action_arg_getMINUS_publicMINUS_key: { arg[1].w = args_info.object_id_arg; if(args_info.object_type_given) { yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse type: "); } else { arg[2].t = YH_ASYMMETRIC_KEY; } arg[3].s = args_info.out_arg; arg[3].len = strlen(args_info.out_arg); comrc = yh_com_get_pubkey(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_PEM : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get public key"); } break; case action_arg_getMINUS_deviceMINUS_pubkey: comrc = yh_com_get_device_pubkey(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_PEM : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get device public key"); break; case action_arg_getMINUS_objectMINUS_info: { if (args_info.object_type_given == 0) { fprintf(stderr, "Missing argument object type\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse type: "); comrc = yh_com_get_object_info(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get object info"); } break; case action_arg_getMINUS_wrapped: { if (args_info.object_type_given == 0) { fprintf(stderr, "Missing argument object-type\n"); rc = EXIT_FAILURE; break; } if (args_info.wrap_id_given == 0) { fprintf(stderr, "Missing argument wrap-id\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.wrap_id_arg; yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse type: "); arg[3].w = args_info.object_id_arg; arg[4].b = args_info.include_seed_given; arg[5].s = args_info.out_arg; arg[5].len = strlen(args_info.out_arg); comrc = yh_com_get_wrapped(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_base64 : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get wrapped object"); } break; case action_arg_getMINUS_rsaMINUS_wrapped: { if (args_info.object_type_given == 0) { fprintf(stderr, "Missing argument object-type\n"); rc = EXIT_FAILURE; break; } if (args_info.wrap_id_given == 0) { fprintf(stderr, "Missing argument wrap-id\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.wrap_id_arg; yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse type: "); arg[3].w = args_info.object_id_arg; yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[4].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); yrc = yh_string_to_algo(args_info.oaep_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse OAEP algorithm: "); yrc = yh_string_to_algo(args_info.mgf1_arg, &arg[6].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse MGF1 algorithm: "); arg[7].s = args_info.out_arg; arg[7].len = strlen(args_info.out_arg); comrc = yh_com_get_rsa_wrapped(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get wrapped object"); } break; case action_arg_getMINUS_rsaMINUS_wrappedMINUS_key: { if (args_info.object_type_given == 0) { fprintf(stderr, "Missing argument object-type\n"); rc = EXIT_FAILURE; break; } if (args_info.wrap_id_given == 0) { fprintf(stderr, "Missing argument wrap-id\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.wrap_id_arg; yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse type: "); arg[3].w = args_info.object_id_arg; yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[4].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); yrc = yh_string_to_algo(args_info.oaep_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse OAEP algorithm: "); yrc = yh_string_to_algo(args_info.mgf1_arg, &arg[6].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse MGF1 algorithm: "); arg[7].s = args_info.out_arg; arg[7].len = strlen(args_info.out_arg); comrc = yh_com_get_rsa_wrapped_key(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get wrapped object"); } break; case action_arg_getMINUS_deviceMINUS_info: comrc = yh_com_get_device_info(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get device info"); break; case action_arg_getMINUS_template: { arg[1].w = args_info.object_id_arg; comrc = yh_com_get_template(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_base64 : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get template object"); } break; case action_arg_listMINUS_objects: { arg[1].w = args_info.object_id_arg; yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse type: "); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); arg[6].s = args_info.label_arg; arg[6].len = strlen(args_info.label_arg); comrc = yh_com_list_objects(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to list objects"); } break; case action_arg_putMINUS_authenticationMINUS_key: { if (args_info.new_password_given == 0) { fprintf(stderr, "Missing argument new-password\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); memset(&arg[5].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.delegated_arg, &arg[5].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); arg[6].x = (uint8_t *) args_info.new_password_arg; arg[6].len = strlen(args_info.new_password_arg); comrc = yh_com_put_authentication(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to store authentication key"); } break; case action_arg_putMINUS_asymmetricMINUS_key: { arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); if (get_input_data(args_info.in_arg, &arg[5].x, &arg[5].len, g_in_fmt == fmt_nofmt ? fmt_PEM : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_asymmetric(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[5].x); COM_SUCCEED_OR_DIE(comrc, "Unable to store asymmetric key"); } break; case action_arg_putMINUS_opaque: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); if (get_input_data(args_info.in_arg, &arg[6].x, &arg[6].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_opaque(&g_ctx, arg, g_in_fmt, fmt_nofmt); free(arg[6].x); COM_SUCCEED_OR_DIE(comrc, "Unable to store opaque object"); } break; case action_arg_putMINUS_option: { if (args_info.opt_name_given == 0) { fprintf(stderr, "Missing argument opt-name\n"); rc = EXIT_FAILURE; break; } if (args_info.opt_value_given == 0) { fprintf(stderr, "Missing argument opt-value\n"); rc = EXIT_FAILURE; break; } yrc = yh_string_to_option(args_info.opt_name_arg, &arg[1].o); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse option name: "); arg[2].x = calloc(ARGS_BUFFER_SIZE, 1); arg[2].len = ARGS_BUFFER_SIZE; if (hex_decode(args_info.opt_value_arg, arg[2].x, &arg[2].len) == false) { fprintf(stderr, "Unable to decode option value\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_option(&g_ctx, arg, fmt_hex, fmt_nofmt); free(arg[2].x); COM_SUCCEED_OR_DIE(comrc, "Unable to put option"); } break; case action_arg_getMINUS_option: { if (args_info.opt_name_given == 0) { fprintf(stderr, "Missing argument opt-name\n"); rc = EXIT_FAILURE; break; } yrc = yh_string_to_option(args_info.opt_name_arg, &arg[1].o); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse option name: "); comrc = yh_com_get_option(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get option"); } break; case action_arg_putMINUS_hmacMINUS_key: LIB_SUCCEED_OR_DIE(YHR_GENERIC_ERROR, "Command not implemented: "); // TODO(adma): this requires a hex parser case action_arg_putMINUS_wrapMINUS_key: { if (args_info.delegated_given == 0) { fprintf(stderr, "Missing delegated capabilities\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); memset(&arg[5].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.delegated_arg, &arg[5].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); if (get_input_data(args_info.in_arg, &arg[6].x, &arg[6].len, g_in_fmt == fmt_nofmt ? fmt_hex : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_wrapkey(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[6].x); COM_SUCCEED_OR_DIE(comrc, "Unable to put wrapkey"); } break; case action_arg_putMINUS_rsaMINUS_wrapkey: { if (args_info.delegated_given == 0) { fprintf(stderr, "Missing delegated capabilities\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); memset(&arg[5].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.delegated_arg, &arg[5].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); if (get_input_data(args_info.in_arg, &arg[6].x, &arg[6].len, g_in_fmt == fmt_nofmt ? fmt_PEM : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_rsa_wrapkey(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[6].x); COM_SUCCEED_OR_DIE(comrc, "Unable to put wrapkey"); } break; case action_arg_putMINUS_publicMINUS_wrapkey: { if (args_info.delegated_given == 0) { fprintf(stderr, "Missing delegated capabilities\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); memset(&arg[5].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.delegated_arg, &arg[5].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); if (get_input_data(args_info.in_arg, &arg[6].x, &arg[6].len, g_in_fmt == fmt_nofmt ? fmt_PEM : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_public_wrapkey(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[6].x); COM_SUCCEED_OR_DIE(comrc, "Unable to put wrapkey"); } break; case action_arg_putMINUS_symmetricMINUS_key: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); if (get_input_data(args_info.in_arg, &arg[6].x, &arg[6].len, g_in_fmt == fmt_nofmt ? fmt_hex : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_symmetric(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[6].x); COM_SUCCEED_OR_DIE(comrc, "Unable to store symmetric key"); } break; case action_arg_putMINUS_wrapped: { if (args_info.wrap_id_given == 0) { fprintf(stderr, "Missing argument wrap-id\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.wrap_id_arg; if (get_input_data(args_info.in_arg, &arg[2].x, &arg[2].len, g_in_fmt == fmt_nofmt ? fmt_base64 : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_wrapped(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[2].x); COM_SUCCEED_OR_DIE(comrc, "Unable to store wrapped object"); } break; case action_arg_putMINUS_rsaMINUS_wrapped: { if (args_info.wrap_id_given == 0) { fprintf(stderr, "Missing argument wrap-id\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.wrap_id_arg; yrc = yh_string_to_algo(args_info.oaep_arg, &arg[2].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse OAEP algorithm: "); yrc = yh_string_to_algo(args_info.mgf1_arg, &arg[3].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse MGF1 algorithm: "); if (get_input_data(args_info.in_arg, &arg[4].x, &arg[4].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_rsa_wrapped(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[4].x); COM_SUCCEED_OR_DIE(comrc, "Unable to store RSA wrapped object"); } break; case action_arg_putMINUS_rsaMINUS_wrappedMINUS_key: { if (args_info.wrap_id_given == 0) { fprintf(stderr, "Missing argument wrap-id\n"); rc = EXIT_FAILURE; break; } if (args_info.object_type_given == 0) { fprintf(stderr, "Missing argument type\n"); rc = EXIT_FAILURE; break; } if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument key-algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.wrap_id_arg; yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse object type: "); arg[3].w = args_info.object_id_arg; yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[4].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse key algorithm: "); arg[5].s = args_info.label_arg; arg[5].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[6].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[7].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.oaep_arg, &arg[8].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse OAEP algorithm: "); yrc = yh_string_to_algo(args_info.mgf1_arg, &arg[9].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse MGF1 algorithm: "); if (get_input_data(args_info.in_arg, &arg[10].x, &arg[10].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_rsa_wrapped_key(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[10].x); COM_SUCCEED_OR_DIE(comrc, "Unable to store RSA wrapped object"); } break; case action_arg_putMINUS_template: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].s = args_info.label_arg; arg[2].len = strlen(args_info.label_arg); yrc = yh_string_to_domains(args_info.domains_arg, &arg[3].w); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse domains: "); memset(&arg[4].c, 0, sizeof(yh_capabilities)); yrc = yh_string_to_capabilities(args_info.capabilities_arg, &arg[4].c); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse capabilities: "); yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[5].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); if (get_input_data(args_info.in_arg, &arg[6].x, &arg[6].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_put_template(&g_ctx, arg, fmt_nofmt, fmt_nofmt); free(arg[6].x); COM_SUCCEED_OR_DIE(comrc, "Unable to store template object"); } break; case action_arg_putMINUS_otpMINUS_aeadMINUS_key: LIB_SUCCEED_OR_DIE(YHR_GENERIC_ERROR, "Command not implemented: "); // TODO(adma): this requires a hex parser case action_arg_signMINUS_eddsa: case action_arg_signMINUS_ecdsa: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[2].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); if (get_input_data(args_info.in_arg, &arg[3].x, &arg[3].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } if (args_info.action_arg[i] == action_arg_signMINUS_ecdsa) { comrc = yh_com_sign_ecdsa(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_base64 : g_out_fmt); } else { comrc = yh_com_sign_eddsa(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_base64 : g_out_fmt); } free(arg[3].x); COM_SUCCEED_OR_DIE(comrc, "Unable to sign data"); } break; case action_arg_signMINUS_pkcs1v15: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[2].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); if (get_input_data(args_info.in_arg, &arg[3].x, &arg[3].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_sign_pkcs1v1_5(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_base64 : g_out_fmt); free(arg[3].x); COM_SUCCEED_OR_DIE(comrc, "Unable to sign data"); } break; case action_arg_signMINUS_pss: { if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[2].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); if (get_input_data(args_info.in_arg, &arg[3].x, &arg[3].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_sign_pss(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_base64 : g_out_fmt); free(arg[3].x); COM_SUCCEED_OR_DIE(comrc, "Unable to sign data"); } break; case action_arg_signMINUS_hmac: LIB_SUCCEED_OR_DIE(YHR_GENERIC_ERROR, "Command not implemented: "); // TODO(adma): this requires a hex parser case action_arg_reset: { comrc = yh_com_reset(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to reset device"); } break; case action_arg_deleteMINUS_object: { if (args_info.object_type_given == 0) { fprintf(stderr, "Missing argument object type\n"); rc = EXIT_FAILURE; break; } yrc = yh_string_to_type(args_info.object_type_arg, &arg[2].t); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse type: "); arg[1].w = args_info.object_id_arg; comrc = yh_com_delete(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to delete object"); } break; case action_arg_signMINUS_sshMINUS_certificate: { if (args_info.template_id_given == 0) { fprintf(stderr, "Missing argument template-id\n"); rc = EXIT_FAILURE; break; } if (args_info.algorithm_given == 0) { fprintf(stderr, "Missing argument algorithm\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].w = args_info.template_id_arg; yrc = yh_string_to_algo(args_info.algorithm_arg, &arg[3].a); LIB_SUCCEED_OR_DIE(yrc, "Unable to parse algorithm: "); if (get_input_data(args_info.in_arg, &arg[4].x, &arg[4].len, g_in_fmt == fmt_nofmt ? fmt_binary : g_in_fmt) == false) { // TODO: correct format? fprintf(stderr, "Failed to get input data\n"); rc = EXIT_FAILURE; break; } comrc = yh_com_sign_ssh_certificate(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); free(arg[4].x); COM_SUCCEED_OR_DIE(comrc, "Unable to get ssh certificate"); } break; case action_arg_benchmark: LIB_SUCCEED_OR_DIE(YHR_GENERIC_ERROR, "Command not implemented: "); case action_arg_createMINUS_otpMINUS_aead: LIB_SUCCEED_OR_DIE(YHR_GENERIC_ERROR, "Command not implemented: "); // TODO(adma): this requires a hex parser case action_arg_randomizeMINUS_otpMINUS_aead: { arg[1].w = args_info.object_id_arg; arg[2].s = args_info.out_arg; arg[2].len = strlen(args_info.out_arg); comrc = yh_com_otp_aead_random(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_binary : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to get aead from random"); } break; case action_arg_decryptMINUS_otp: LIB_SUCCEED_OR_DIE(YHR_GENERIC_ERROR, "Command not implemented: "); // TODO(adma): this requires a hex parser case action_arg_signMINUS_attestationMINUS_certificate: { if (args_info.attestation_id_given == 0) { fprintf(stderr, "Missing argument attestation-id\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.object_id_arg; arg[2].w = args_info.attestation_id_arg; comrc = yh_com_sign_attestation_certificate(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_PEM : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to attest asymmetric key"); } break; case action_arg_getMINUS_logs: { comrc = yh_com_audit(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_ASCII : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to extract logs"); } break; case action_arg_setMINUS_logMINUS_index: { if (args_info.log_index_given == 0) { fprintf(stderr, "Missing argument log-index\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.log_index_arg; comrc = yh_com_set_log_index(&g_ctx, arg, fmt_nofmt, g_out_fmt == fmt_nofmt ? fmt_ASCII : g_out_fmt); COM_SUCCEED_OR_DIE(comrc, "Unable to set log index"); } break; case action_arg_blinkMINUS_device: { if (args_info.duration_arg < 0 || args_info.duration_arg > 0xff) { fprintf(stderr, "Duration must be in [0, 256]\n"); rc = EXIT_FAILURE; break; } arg[1].w = args_info.duration_arg; comrc = yh_com_blink(&g_ctx, arg, fmt_nofmt, fmt_nofmt); COM_SUCCEED_OR_DIE(comrc, "Unable to blink device"); } break; case action__NULL: printf("ERROR !%u \n", args_info.action_given); rc = EXIT_FAILURE; } if (rc == EXIT_FAILURE) { break; } } calling_device = false; } else { int num = 0; #ifndef __WIN32 EditLine *el; HistEvent ev; g_hist = history_init(); history(g_hist, &ev, H_SETSIZE, 1000); // NOTE(adma): 1000 history items el = el_init(*argv, stdin, stdout, stderr); el_set(el, EL_EDITOR, "emacs"); #ifdef EL_PROMPT_ESC el_set(el, EL_PROMPT_ESC, prompt, '\1'); /* Set the prompt function */ #else el_set(el, EL_PROMPT, prompt); /* Set the prompt function */ #endif /* EL_PROMPT_ESC */ el_set(el, EL_HIST, history, g_hist); /* enable ctrl-R for reverse history search */ el_set(el, EL_BIND, "^R", "em-inc-search-prev", NULL); /* Add a user-defined function */ el_set(el, EL_ADDFN, "yh_complete", "Complete argument", yubihsm_complete); /* Bind tab to it */ el_set(el, EL_BIND, "^I", "yh_complete", NULL); el_source(el, NULL); // NOTE(adma): source the user's defaults file #endif create_command_list(&g_commands); if (args_info.pre_connect_flag) { yh_com_connect(&g_ctx, NULL, fmt_nofmt, fmt_nofmt); } while (g_running == true) { #ifdef __WIN32 fprintf(stdout, PROMPT); char data[1025]; char *buf = converting_fgets(data, sizeof(data), stdin); if (buf) { num = strlen(buf); } #else const char *buf = el_gets(el, &num); #endif if (buf == NULL) { // NOTE(adma): got Ctrl-D yh_com_quit(NULL, NULL, fmt_nofmt, fmt_nofmt); fprintf(stdout, "\n"); } else if (num > 0 && buf[0] != '\n' && buf[0] != '\r') { #ifndef __WIN32 history(g_hist, &ev, H_ENTER, buf); #endif validate_and_call(&g_ctx, g_commands, buf); } } #ifndef __WIN32 el_end(el); history_end(g_hist); #endif } main_exit: calling_device = true; for (size_t i = 0; i < sizeof(g_ctx.sessions) / sizeof(g_ctx.sessions[0]); i++) { if (g_ctx.sessions[i]) { yh_util_close_session(g_ctx.sessions[i]); yh_destroy_session(&g_ctx.sessions[i]); } } yh_disconnect(g_ctx.connector); cmdline_parser_free(&args_info); if (g_ctx.out != stdout && g_ctx.out != NULL) { fclose(g_ctx.out); } if (g_ctx.cacert) { free(g_ctx.cacert); } if (g_ctx.cert) { free(g_ctx.cert); } if (g_ctx.key) { free(g_ctx.key); } if (g_ctx.proxy) { free(g_ctx.proxy); } if (g_ctx.noproxy) { free(g_ctx.noproxy); } yh_exit(); ykhsmauth_done(g_ctx.state); g_ctx.state = NULL; free_configured_pubkeys(&g_ctx); free_configured_connectors(&g_ctx); return rc; } yubihsm-shell-2.6.0/src/cmdline.ggo0000644000175100001770000001633714666527773016612 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # option "action" a "Action to perform" values="benchmark", "blink-device", "create-otp-aead", "decrypt-aesccm", "decrypt-aescbc", "decrypt-aesecb", "decrypt-oaep", "decrypt-otp", "decrypt-pkcs1v15", "delete-object", "derive-ecdh", "encrypt-aesccm", "encrypt-aescbc", "encrypt-aesecb", "generate-asymmetric-key", "generate-hmac-key", "generate-otp-aead-key", "generate-wrap-key", "generate-symmetric-key", "get-device-info", "get-logs", "get-object-info", "get-opaque", "get-option", "get-pseudo-random", "get-public-key", "get-storage-info", "get-template", "get-wrapped", "get-rsa-wrapped", "get-rsa-wrapped-key", "get-device-pubkey", "list-objects", "put-asymmetric-key", "put-authentication-key", "put-hmac-key", "put-opaque", "put-option", "put-otp-aead-key", "put-symmetric-key", "put-template", "put-wrap-key", "put-rsa-wrapkey", "put-public-wrapkey", "put-wrapped", "put-rsa-wrapped", "put-rsa-wrapped-key", "randomize-otp-aead", "reset", "set-log-index", "sign-attestation-certificate", "sign-ecdsa", "sign-eddsa", "sign-hmac", "sign-pkcs1v15", "sign-pss", "sign-ssh-certificate" enum optional multiple option "password" p "Authentication password" string optional option "authkey" - "Authentication key" int optional default="1" option "object-id" i "Object ID" short optional default="0" option "label" l "Object label" string optional default="" option "domains" d "Object domains" string optional default="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16" option "capabilities" c "Capabilities for an object" string optional default="0" option "object-type" t "Object type" string optional default="any" option "ykhsmauth-label" y "Credential label on YubiKey (implicitly enables ykhsmauth)" string optional option "ykhsmauth-reader" r "Only use a matching YubiKey reader name" string optional default="" option "delegated" - "Delegated capabilities" string optional default="0" option "new-password" - "New authentication password" string optional option "algorithm" A "Operation algorithm" string optional default="any" option "oaep" - "OAEP algorithm. Used primarily with asymmetric wrap" string optional default="rsa-oaep-sha256" option "mgf1" - "MGF1 algorithm. Used primarily with asymmetric wrap" string optional default="mgf1-sha256" option "nonce" - "OTP nonce" int optional option "iv" - "An initialization vector as a hexadecimal string" string optional option "count" - "Number of bytes to request" int optional default="256" option "duration" - "Blink duration in seconds" int optional default="10" option "wrap-id" - "Wrap key ID" int optional option "include-seed" - "Include seed when exporting an ED25519 key under wrap" flag off option "template-id" - "Template ID" int optional option "attestation-id" - "Attestation ID" int optional option "log-index" - "Log index" int optional option "opt-name" - "Device option name" string optional option "opt-value" - "Device option value" string optional option "in" - "Input data (filename)" string optional default="-" option "out" - "Output data (filename)" string optional default="-" option "informat" - "Input format" values="default","base64","binary","PEM","password","hex","ASCII" enum optional default="default" option "outformat" - "Input and output format" values="default","base64","binary","PEM","hex","ASCII" enum optional default="default" #option "enc-key" e "Encryption key to use" string optional default="404142434445464748494a4b4c4d4e4f" #option "mac-key" m "Mac key to use" string optional default="404142434445464748494a4b4c4d4e4f" option "config-file" f "Configuration file to read" string optional default="" option "connector" C "List of connectors to use" string optional multiple option "cacert" - "HTTPS cacert for connector" string optional option "cert" - "HTTPS client certificate to authenticate with" string optional option "key" - "HTTPS client certificate key" string optional option "proxy" - "Proxy server to use for connector" string optional option "noproxy" - "Comma separated list of hosts ignore proxy for" string optional option "verbose" v "Print more information" int optional default="0" option "pre-connect" P "Connect immediately in interactive mode" flag off option "device-pubkey" - "List of device public keys allowed for asymmetric authentication" string optional multiple yubihsm-shell-2.6.0/src/commands.c0000644000175100001770000034473514666527773016454 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include "commands.h" #include "yubihsm-shell.h" #include "../common/insecure_memzero.h" #include "../common/parsing.h" #include "time_win.h" #include "hash.h" #include "util.h" #include "openssl-compat.h" #ifdef __WIN32 #include #include #else #include #include #include #include #endif #include #include #include #include #include static format_t fmt_to_fmt(cmd_format fmt) { switch (fmt) { case fmt_base64: return _base64; case fmt_binary: return _binary; case fmt_hex: return _hex; case fmt_PEM: return _PEM; default: return 0; } } // NOTE(adma): Extract log entries // argc = 1 // arg 0: e:session int yh_com_audit(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); uint16_t unlogged_boot = 0; uint16_t unlogged_auth = 0; yh_log_entry logs[YH_MAX_LOG_ENTRIES] = {0}; size_t n_items = sizeof(logs) / sizeof(logs[0]); switch (fmt) { case fmt_binary: case fmt_PEM: case fmt_base64: case fmt_password: fprintf(stderr, "The selected output format is not supported for this operation. " "Supported format are \"ASCII\", \"hex\" and \"default\"\n"); return -1; default: break; } yh_rc yrc = yh_util_get_log_entries(argv[0].e, &unlogged_boot, &unlogged_auth, logs, &n_items); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get logs: %s\n", yh_strerror(yrc)); return -1; } char digest_buf[(2 * YH_LOG_DIGEST_SIZE) + 1] = {0}; switch (fmt) { case fmt_hex: fprintf(ctx->out, "%04x%04x", unlogged_boot, unlogged_auth); for (size_t i = 0; i < n_items; i++) { format_digest(logs[i].digest, digest_buf, YH_LOG_DIGEST_SIZE); fprintf(ctx->out, "%04x%02x%04x%04x%04x%04x%02x%08lx%s", logs[i].number, logs[i].command, logs[i].length, logs[i].session_key, logs[i].target_key, logs[i].second_key, logs[i].result, (unsigned long) logs[i].systick, digest_buf); } fprintf(ctx->out, "\n"); break; case fmt_ASCII: default: fprintf(ctx->out, "%d unlogged boots found\n", unlogged_boot); fprintf(ctx->out, "%d unlogged authentications found\n", unlogged_auth); if (n_items == 0) { fprintf(ctx->out, "No logs to extract\n"); return 0; } else if (n_items == 1) { fprintf(ctx->out, "Found 1 item\n"); } else { fprintf(ctx->out, "Found %zu items\n", n_items); } for (size_t i = 0; i < n_items; i++) { format_digest(logs[i].digest, digest_buf, YH_LOG_DIGEST_SIZE); fprintf(ctx->out, "item: %5u -- cmd: 0x%02x -- length: %4u -- session key: " "0x%04x -- target key: 0x%04x -- second key: 0x%04x -- " "result: 0x%02x -- tick: %lu -- hash: %s\n", logs[i].number, logs[i].command, logs[i].length, logs[i].session_key, logs[i].target_key, logs[i].second_key, logs[i].result, (unsigned long) logs[i].systick, digest_buf); } break; } return 0; } // NOTE: Set the log index // argc = 2 // arg 0: e:session // arg 1: w:index int yh_com_set_log_index(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_set_log_index(argv[0].e, argv[1].w); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to set log index: %s\n", yh_strerror(yrc)); return -1; } return 0; } // NOTE: Blink the device // argc = 2 // arg 0: e:session // arg 1: b:seconds int yh_com_blink(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); UNUSED(ctx); yh_rc yrc = yh_util_blink_device(argv[0].e, argv[1].b); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to blink the device: %s\n", yh_strerror(yrc)); return -1; } return 0; } // NOTE(adma): Close a session with a connector // argc = 1 // arg 0: e:session int yh_com_close_session(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); uint8_t session_id = 0; yh_rc yrc = yh_get_session_id(argv[0].e, &session_id); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get session id: %s\n", yh_strerror(yrc)); return -1; } yrc = yh_util_close_session(argv[0].e); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to close session: %s\n", yh_strerror(yrc)); return -1; } yrc = yh_destroy_session(&argv[0].e); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to destroy session: %s\n", yh_strerror(yrc)); return -1; } ctx->sessions[session_id] = NULL; return 0; } // NOTE(adma): Connect to a connector // argc = 0 int yh_com_connect(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); ctx->connector = NULL; for (int i = 0; ctx->connector_list[i]; i++) { if (ctx->connector) { yh_disconnect(ctx->connector); ctx->connector = NULL; } yh_rc yrc = yh_init_connector(ctx->connector_list[i], &ctx->connector); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed initializing connector %s: %s\n", ctx->connector_list[i], yh_strerror(yrc)); break; } if (ctx->cacert) { if (yh_set_connector_option(ctx->connector, YH_CONNECTOR_HTTPS_CA, ctx->cacert) != YHR_SUCCESS) { fprintf(stderr, "Failed setting HTTPS CA\n"); break; } } if (ctx->cert) { if (yh_set_connector_option(ctx->connector, YH_CONNECTOR_HTTPS_CERT, ctx->cert) != YHR_SUCCESS) { fprintf(stderr, "Failed setting HTTPS cert\n"); break; } } if (ctx->key) { if (yh_set_connector_option(ctx->connector, YH_CONNECTOR_HTTPS_KEY, ctx->key) != YHR_SUCCESS) { fprintf(stderr, "Failed setting HTTPS key\n"); break; } } if (ctx->proxy) { if (yh_set_connector_option(ctx->connector, YH_CONNECTOR_PROXY_SERVER, ctx->proxy) != YHR_SUCCESS) { fprintf(stderr, "Failed setting proxy server\n"); break; } } if (ctx->noproxy) { if (yh_set_connector_option(ctx->connector, YH_CONNECTOR_NOPROXY, ctx->noproxy) != YHR_SUCCESS) { fprintf(stderr, "Failed setting noproxy\n"); break; } } yrc = yh_connect(ctx->connector, 0); if (yrc == YHR_SUCCESS) { (void) yh_com_keepalive_on(NULL, NULL, fmt_nofmt, fmt_nofmt); return 0; } fprintf(stderr, "Failed connecting '%s': %s\n", ctx->connector_list[i], yh_strerror(yrc)); } if (ctx->connector) { yh_disconnect(ctx->connector); ctx->connector = NULL; } return -1; } // NOTE(adma): Enable all debug messages // argc = 0 int yh_com_debug_all(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); yh_set_verbosity(ctx->connector, YH_VERB_ALL); fprintf(stderr, "Debug messages enabled\n"); return 0; } // NOTE(adma): Toggle debug messages // argc = 0 int yh_com_debug_error(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); uint8_t yh_verbosity = 0; yh_get_verbosity(&yh_verbosity); yh_verbosity ^= YH_VERB_ERR; if (yh_verbosity & YH_VERB_ERR) fprintf(stderr, "Error messages on\n"); else fprintf(stderr, "Error messages off\n"); yh_set_verbosity(ctx->connector, yh_verbosity); return 0; } // NOTE(adma): Toggle debug messages // argc = 0 int yh_com_debug_info(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); uint8_t yh_verbosity = 0; yh_get_verbosity(&yh_verbosity); yh_verbosity ^= YH_VERB_INFO; if (yh_verbosity & YH_VERB_INFO) fprintf(stderr, "Info messages on\n"); else fprintf(stderr, "Info messages off\n"); yh_set_verbosity(ctx->connector, yh_verbosity); return 0; } // NOTE(adma): Toggle debug messages // argc = 0 int yh_com_debug_intermediate(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); uint8_t yh_verbosity = 0; yh_get_verbosity(&yh_verbosity); yh_verbosity ^= YH_VERB_INTERMEDIATE; if (yh_verbosity & YH_VERB_INTERMEDIATE) fprintf(stderr, "Intermediate messages on\n"); else fprintf(stderr, "Intermediate messages off\n"); yh_set_verbosity(ctx->connector, yh_verbosity); return 0; } // NOTE(adma): Toggle debug messages // argc = 0 int yh_com_debug_none(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); yh_set_verbosity(ctx->connector, YH_VERB_QUIET); fprintf(stderr, "Debug messages disabled\n"); return 0; } // NOTE(adma): Toggle debug messages // argc = 0 int yh_com_debug_raw(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); uint8_t yh_verbosity = 0; yh_get_verbosity(&yh_verbosity); yh_verbosity ^= YH_VERB_RAW; if (yh_verbosity & YH_VERB_RAW) fprintf(stderr, "Raw messages on\n"); else fprintf(stderr, "Raw messages off\n"); yh_set_verbosity(ctx->connector, yh_verbosity); return 0; } // NOTE(adma): Toggle debug messages // argc = 0 int yh_com_debug_crypto(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); uint8_t yh_verbosity = 0; yh_get_verbosity(&yh_verbosity); yh_verbosity ^= YH_VERB_CRYPTO; if (yh_verbosity & YH_VERB_CRYPTO) fprintf(stderr, "Crypto messages on\n"); else fprintf(stderr, "Crypto messages off\n"); yh_set_verbosity(ctx->connector, yh_verbosity); return 0; } // NOTE(adma): Decrypt data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:data int yh_com_decrypt_pkcs1v1_5(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_decrypt_pkcs1v1_5(argv[0].e, argv[1].w, argv[2].x, argv[2].len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to decrypt data: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Do a ECDH key exchange // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:pubkey int yh_com_derive_ecdh(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); yh_algorithm algo = 0; uint8_t data[YH_MSG_BUF_SIZE] = {0}; size_t data_len = sizeof(data); if (!read_public_key(argv[2].x, argv[2].len, &algo, data, &data_len)) { fprintf(stderr, "Failed to load public key\n"); return -1; } uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_derive_ecdh(argv[0].e, argv[1].w, data, data_len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to do key exchange: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Decrypt data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:data int yh_com_decrypt_aesccm(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_unwrap_data(argv[0].e, argv[1].w, argv[2].x, argv[2].len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to decrypt data: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Encrypt data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:data int yh_com_encrypt_aesccm(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_wrap_data(argv[0].e, argv[1].w, argv[2].x, argv[2].len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to encrypt data: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Decrypt data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:data int yh_com_decrypt_aes_ecb(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); yh_rc yrc = yh_util_decrypt_aes_ecb(argv[0].e, argv[1].w, argv[2].x, argv[2].len, argv[2].x, &argv[2].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to decrypt data: %s\n", yh_strerror(yrc)); return -1; } write_file(argv[2].x, argv[2].len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Encrypt data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: s:iv // arg 3: i:data int yh_com_encrypt_aes_cbc(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); uint8_t iv[16] = {0}; size_t iv_len = sizeof(iv); if (hex_decode(argv[2].s, iv, &iv_len) == false) { fprintf(stderr, "Failed to decode IV\n"); return -1; } yh_rc yrc = yh_util_encrypt_aes_cbc(argv[0].e, argv[1].w, iv, argv[3].x, argv[3].len, argv[3].x, &argv[3].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to encrypt data: %s\n", yh_strerror(yrc)); return -1; } write_file(argv[3].x, argv[3].len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Decrypt data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: s:iv // arg 3: i:data int yh_com_decrypt_aes_cbc(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); uint8_t iv[16] = {0}; size_t iv_len = sizeof(iv); if (hex_decode(argv[2].s, iv, &iv_len) == false) { fprintf(stderr, "Failed to decode IV\n"); return -1; } yh_rc yrc = yh_util_decrypt_aes_cbc(argv[0].e, argv[1].w, iv, argv[3].x, argv[3].len, argv[3].x, &argv[3].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to decrypt data: %s\n", yh_strerror(yrc)); return -1; } write_file(argv[3].x, argv[3].len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Encrypt data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:data int yh_com_encrypt_aes_ecb(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(ctx); yh_rc yrc = yh_util_encrypt_aes_ecb(argv[0].e, argv[1].w, argv[2].x, argv[2].len, argv[2].x, &argv[2].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to encrypt data: %s\n", yh_strerror(yrc)); return -1; } write_file(argv[2].x, argv[2].len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE(adma): Disconnect from a connector // argc = 0 int yh_com_disconnect(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = YHR_SUCCESS; for (size_t i = 0; i < sizeof(ctx->sessions) / sizeof(ctx->sessions[0]); i++) { if (ctx->sessions[i]) { yrc = yh_util_close_session(ctx->sessions[i]); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to close session: %s\n", yh_strerror(yrc)); } yrc = yh_destroy_session(&ctx->sessions[i]); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to destroy session: %s\n", yh_strerror(yrc)); } ctx->sessions[i] = NULL; } } if (ctx->connector) { yrc = yh_disconnect(ctx->connector); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Unable to disconnect: %s\n", yh_strerror(yrc)); return -1; } ctx->connector = NULL; } return 0; } // NOTE(adma): Send authenticated echo // argc = 3 // arg 0: e:session // arg 1: b:byte // arg 2: w:count int yh_com_echo(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); uint8_t data[YH_MSG_BUF_SIZE] = {0}; size_t data_len = 0; uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = 0; yh_cmd response_cmd = 0; uint8_t byte = argv[1].b; uint16_t count = argv[2].w; if (count > YH_MSG_BUF_SIZE) { fprintf(stderr, "Count must be in [0, %d]\n", YH_MSG_BUF_SIZE); return -1; } memset(data, byte, count); data_len = count; response_len = sizeof(response); yh_rc yrc = yh_send_secure_msg(argv[0].e, YHC_ECHO, data, data_len, &response_cmd, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to send ECHO command: %s\n", yh_strerror(yrc)); return -1; } fprintf(ctx->out, "Response (%zu bytes):\n", response_len); for (size_t i = 0; i < response_len; i++) { if (i && !(i % 64)) fprintf(ctx->out, "\n"); else if (i && !(i % 8)) fprintf(ctx->out, " "); fprintf(ctx->out, "%02x", response[i]); } fprintf(ctx->out, "\n"); return 0; } // Generate a Symmetric Key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm int yh_com_generate_symmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc; if (yh_is_aes(argv[5].a)) { yrc = yh_util_generate_aes_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a); } else { fprintf(stderr, "Invalid algorithm %d\n", argv[5].a); return -1; } if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to generate symmetric key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Generated symmetric key 0x%04x\n", argv[1].w); return 0; } // NOTE(adma): Generate an Asymmetric Key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm int yh_com_generate_asymmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = YHR_SUCCESS; if (yh_is_rsa(argv[5].a)) { yrc = yh_util_generate_rsa_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a); } else if (yh_is_ec(argv[5].a)) { yrc = yh_util_generate_ec_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a); } else if (yh_is_ed(argv[5].a)) { yrc = yh_util_generate_ed_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a); } else { fprintf(stderr, "Invalid algorithm %d\n", argv[5].a); return -1; } if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to generate asymmetric key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Generated Asymmetric key 0x%04x\n", argv[1].w); return 0; } // NOTE: Generate HMAC key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm int yh_com_generate_hmac(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); if (!yh_is_hmac(argv[5].a)) { fprintf(stderr, "Invalid algorithm: %d\n", argv[5].a); return -1; } yh_rc yrc = yh_util_generate_hmac_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to generate HMAC key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Generated HMAC key 0x%04x\n", argv[1].w); return 0; } // NOTE: Generate wrap key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: c:delegated_capabilities // arg 6: a:algorithm int yh_com_generate_wrap(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_generate_wrap_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[6].a, &argv[5].c); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to generate wrapping key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Generated Wrap key 0x%04x\n", argv[1].w); return 0; } // NOTE(adma): Get an opaque object // argc = 2 // arg 0: e:session, // arg 1: w:object_id // arg 2: F:file int yh_com_get_opaque(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); int ret = -1; yh_rc yrc = yh_util_get_opaque(argv[0].e, argv[1].w, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get opaque object: %s\n", yh_strerror(yrc)); return -1; } if (fmt == fmt_PEM) { const unsigned char *ptr = response; X509 *x509 = d2i_X509(NULL, &ptr, response_len); if (!x509) { fprintf(stderr, "Failed parsing x509 information\n"); } else { if (PEM_write_X509(ctx->out, x509) == 1) { ret = 0; } else { fprintf(stderr, "Failed writing x509 information\n"); } } X509_free(x509); } else { if (write_file(response, response_len, ctx->out, fmt_to_fmt(fmt))) { ret = 0; } } return ret; } // NOTE(adma): Get a global option value // argc = 2 // arg 0: o:session // arg 1: s:option int yh_com_get_option(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_get_option(argv[0].e, argv[1].o, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get option: %s\n", yh_strerror(yrc)); return -1; } fprintf(ctx->out, "Option value is: "); for (size_t i = 0; i < response_len; i++) { fprintf(ctx->out, "%02x", response[i]); } fprintf(ctx->out, "\n"); return 0; } // NOTE(adma): Get pseudo-random bytes // argc = 2 // arg 0: e:session // arg 1: w:count int yh_com_get_random(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_get_pseudo_random(argv[0].e, argv[1].w, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get pseudo random bytes: %s\n", yh_strerror(yrc)); return -1; } if (response_len != argv[1].w) { fprintf(stderr, "Wrong response length\n"); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE(adma): Obtain storage information // argc = 1 // arg 0: e:session int yh_com_get_storage(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); uint16_t total_records = 0, free_records = 0, free_pages = 0, total_pages = 0, page_size = 0; yh_rc yrc = yh_util_get_storage_info(argv[0].e, &total_records, &free_records, &total_pages, &free_pages, &page_size); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get storage stats: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "free records: %d/%d, free pages: %d/%d page size: %d bytes\n", free_records, total_records, free_pages, total_pages, page_size); return 0; } // NOTE: Get public key // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: t:key_type // arg 3: f:filename int yh_com_get_pubkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_algorithm algo = 0; EVP_PKEY *public_key = NULL; yh_rc yrc = yh_util_get_public_key_ex(argv[0].e, argv[2].t, argv[1].w, response, &response_len, &algo); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get public key: %s\n", yh_strerror(yrc)); return -1; } public_key = EVP_PKEY_new(); if (public_key == NULL) { fprintf(stderr, "Failed to create public key\n"); return -1; } if (yh_is_rsa(algo)) { RSA *rsa = RSA_new(); if (rsa == NULL) { fprintf(stderr, "Failed to create RSA key\n"); return -1; } BIGNUM *e = BN_new(); BIGNUM *n = BN_bin2bn(response, response_len, NULL); BN_set_word(e, 0x010001); if (RSA_set0_key(rsa, n, e, NULL) != 1) { fprintf(stderr, "Failed to set RSA key\n"); RSA_free(rsa); return -1; } if (EVP_PKEY_set1_RSA(public_key, rsa) != 1) { fprintf(stderr, "Failed to set RSA key\n"); RSA_free(rsa); return -1; } RSA_free(rsa); } else if (yh_is_ec(algo)) { bool error = false; EC_KEY *eckey = EC_KEY_new(); if (eckey == NULL) { fprintf(stderr, "Failed to create EC key\n"); return -1; } int nid = algo2nid(algo); EC_POINT *point = NULL; EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { fprintf(stderr, "Failed to create EC group from curve name\n"); error = true; goto ec_cleanup; } EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); if (EC_KEY_set_group(eckey, group) != 1) { fprintf(stderr, "Failed to set EC group\n"); error = true; goto ec_cleanup; } point = EC_POINT_new(group); memmove(response + 1, response, response_len); response[0] = 0x04; // hack to make it a valid ec pubkey.. response_len++; if (EC_POINT_oct2point(group, point, response, response_len, NULL) != 1) { fprintf(stderr, "Failed to parse EC point\n"); error = true; goto ec_cleanup; } if (EC_KEY_set_public_key(eckey, point) != 1) { fprintf(stderr, "Failed to set EC public key\n"); error = true; goto ec_cleanup; } if (EVP_PKEY_set1_EC_KEY(public_key, eckey) != 1) { fprintf(stderr, "Failed to set EC public key\n"); error = true; } ec_cleanup: if (point != NULL) { EC_POINT_free(point); } if (eckey != NULL) { EC_KEY_free(eckey); } if (group != NULL) { EC_GROUP_free(group); } if (error) { return -1; } } else { // NOTE(adma): ED25519, there is (was) no support for this in // OpenSSL, so we manually export them EVP_PKEY_free(public_key); if (write_ed25519_key(response, response_len, ctx->out, fmt_to_fmt(fmt)) == false) { fprintf(stderr, "Unable to format ed25519 key\n"); return -1; } return 0; } if (fmt == fmt_PEM) { if (PEM_write_PUBKEY(ctx->out, public_key) != 1) { fprintf(stderr, "Failed to write public key in PEM format\n"); EVP_PKEY_free(public_key); return -1; } } else if (fmt == fmt_binary) { i2d_PUBKEY_fp(ctx->out, public_key); } else if (fmt == fmt_base64) { bool error = false; BIO *b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { fprintf(stderr, "Unable to allocate buffer\n"); error = true; goto getpk_base64_cleanup; } BIO *bio = BIO_new_fp(ctx->out, BIO_NOCLOSE); if (bio == NULL) { fprintf(stderr, "Unable to allocate BIO\n"); BIO_free_all(b64); error = true; goto getpk_base64_cleanup; } bio = BIO_push(b64, bio); (void) i2d_PUBKEY_bio(bio, public_key); (void) BIO_flush(bio); (void) BIO_free_all(bio); getpk_base64_cleanup: if (error) { EVP_PKEY_free(public_key); return -1; } } // FIXME: other formats or error. EVP_PKEY_free(public_key); return 0; } // NOTE: Get device public key // argc = 0 int yh_com_get_device_pubkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(argv); UNUSED(in_fmt); if (ctx->connector == NULL) { fprintf(stderr, "Not connected\n"); return -1; } uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_algorithm algo = 0; yh_rc yrc = yh_util_get_device_pubkey(ctx->connector, response, &response_len, &algo); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get device pubkey: %s\n", yh_strerror(yrc)); return -1; } if (fmt == fmt_hex) { for (size_t i = 0; i < response_len; i++) { fprintf(ctx->out, "%02x", response[i]); } fprintf(ctx->out, "\n"); return 0; } int nid = algo2nid(algo); EC_GROUP *group = EC_GROUP_new_by_curve_name(nid); if (group == NULL) { fprintf(stderr, "Invalid device public key algorithm\n"); return -1; } EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); EC_KEY *eckey = EC_KEY_new(); EC_KEY_set_group(eckey, group); EC_POINT *point = EC_POINT_new(group); EC_POINT_oct2point(group, point, response, response_len, NULL); EC_KEY_set_public_key(eckey, point); EVP_PKEY *public_key = EVP_PKEY_new(); EVP_PKEY_set1_EC_KEY(public_key, eckey); EC_POINT_free(point); EC_KEY_free(eckey); EC_GROUP_free(group); if (fmt == fmt_PEM) { PEM_write_PUBKEY(ctx->out, public_key); } else if (fmt == fmt_binary) { i2d_PUBKEY_fp(ctx->out, public_key); } else if (fmt == fmt_base64) { bool error = false; BIO *b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { fprintf(stderr, "Unable to allocate buffer\n"); error = true; goto getdpk_base64_cleanup; } BIO *bio = BIO_new_fp(ctx->out, BIO_NOCLOSE); if (bio == NULL) { fprintf(stderr, "Unable to allocate BIO\n"); BIO_free_all(b64); error = true; goto getdpk_base64_cleanup; } bio = BIO_push(b64, bio); (void) i2d_PUBKEY_bio(bio, public_key); (void) BIO_flush(bio); (void) BIO_free_all(bio); getdpk_base64_cleanup: if (error) { EVP_PKEY_free(public_key); return -1; } } // FIXME: other formats or error. EVP_PKEY_free(public_key); return 0; } // NOTE: Get object information // argc = 3 // arg 0: e:session // arg 1: w:id // arg 2: t:type int yh_com_get_object_info(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { yh_object_descriptor object = {0}; UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_get_object_info(argv[0].e, argv[1].w, argv[2].b, &object); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get object info: %s\n", yh_strerror(yrc)); return -1; } char domains[256] = {0}; const char *cap[sizeof(yh_capability) / sizeof(yh_capability[0])] = {0}; size_t n_cap = sizeof(yh_capability) / sizeof(yh_capability[0]); const char *type = 0; const char *algorithm = ""; const char *extra_algo = ""; char *label = object.label; size_t label_len = strlen(label); yh_type_to_string(object.type, &type); if (object.algorithm) { yh_algo_to_string(object.algorithm, &algorithm); extra_algo = ", algorithm: "; } yh_domains_to_string(object.domains, domains, 255); for (size_t i = 0; i < label_len; i++) { if (isprint(label[i]) == 0) { label[i] = '.'; } } fprintf(ctx->out, "id: 0x%04x, type: %s%s%s, label: \"%s\", length: %d, " "domains: %s, sequence: %hhu, origin: ", object.id, type, extra_algo, algorithm, label, object.len, domains, object.sequence); if (object.origin & YH_ORIGIN_GENERATED) { fprintf(ctx->out, "generated"); } if (object.origin & YH_ORIGIN_IMPORTED) { fprintf(ctx->out, "imported"); } if (object.origin & YH_ORIGIN_IMPORTED_WRAPPED) { fprintf(ctx->out, ":imported_wrapped"); } fprintf(ctx->out, ", capabilities: "); if (yh_capabilities_to_strings(&object.capabilities, cap, &n_cap) != YHR_SUCCESS) { for (size_t i = 0; i < YH_CAPABILITIES_LEN; i++) { fprintf(ctx->out, "0x%02x%s", object.capabilities.capabilities[i], i < YH_CAPABILITIES_LEN - 1 ? " " : ""); } } else { for (size_t i = 0; i < n_cap; i++) { fprintf(ctx->out, "%s%s", cap[i], i < n_cap - 1 ? ":" : ""); } } if (object.type == YH_WRAP_KEY || object.type == YH_AUTHENTICATION_KEY) { fprintf(ctx->out, ", delegated_capabilities: "); n_cap = sizeof(yh_capability) / sizeof(yh_capability[0]); if (yh_capabilities_to_strings(&object.delegated_capabilities, cap, &n_cap) != YHR_SUCCESS) { for (size_t i = 0; i < YH_CAPABILITIES_LEN; i++) { fprintf(ctx->out, "0x%02x%s", object.delegated_capabilities.capabilities[i], i < YH_CAPABILITIES_LEN - 1 ? " " : ""); } } else { for (size_t i = 0; i < n_cap; i++) { fprintf(ctx->out, "%s%s", cap[i], i < n_cap - 1 ? ":" : ""); } } } fprintf(ctx->out, "\n"); return 0; } // NOTE: Get an object under wrap // argc = 5 // arg 0: e:session // arg 1: w:keyid // arg 2: t:type // arg 3: w:id // arg 4: b:include_seed // arg 5: f:file int yh_com_get_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); UNUSED(in_fmt); uint8_t format = argv[4].b ? 1 : 0; yh_rc yrc = yh_util_export_wrapped_ex(argv[0].e, argv[1].w, argv[2].b, argv[3].w, format, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get wrapped object: %s\n", yh_strerror(yrc)); return -1; } if (write_file(response, response_len, ctx->out, fmt_to_fmt(fmt))) { return 0; } return -1; } // NOTE: Get an RSA wrapped key or object // argc = 7 // arg 0: e:session // arg 1: w:keyid // arg 2: t:type // arg 3: w:id // arg 4: a:aes // arg 5: a:oaep // arg 6: a:mgf1 // arg 7: f:file static int do_rsa_wrap(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt, bool key_wrap) { UNUSED(in_fmt); int hash = 0; yh_algorithm aes = argv[4].a; yh_algorithm oaep = argv[5].a; yh_algorithm mgf1 = argv[6].a; yh_rc yrc; if (aes == 0) { aes = YH_ALGO_AES256; } switch (oaep) { case YH_ALGO_RSA_OAEP_SHA1: hash = _SHA1; break; case YH_ALGO_RSA_OAEP_SHA256: hash = _SHA256; break; case YH_ALGO_RSA_OAEP_SHA384: hash = _SHA384; break; case YH_ALGO_RSA_OAEP_SHA512: hash = _SHA512; break; default: fprintf(stderr, "Unrecognized OAEP algorithm\n"); return -1; } uint8_t label[64] = {0}; size_t label_len = sizeof(label); if (hash_bytes(NULL, 0, hash, label, &label_len) == false) { fprintf(stderr, "Unable to hash data\n"); return -1; } uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); if (key_wrap) { yrc = yh_util_get_rsa_wrapped_key(argv[0].e, argv[1].w, argv[2].b, argv[3].w, aes, oaep, mgf1, label, label_len, response, &response_len); } else { yrc = yh_util_export_rsa_wrapped(argv[0].e, argv[1].w, argv[2].b, argv[3].w, aes, oaep, mgf1, label, label_len, response, &response_len); } if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to encrypt data with OAEP: %s\n", yh_strerror(yrc)); return yrc; } if (!write_file(response, response_len, ctx->out, fmt_to_fmt(fmt))) { fprintf(stderr, "Failed to write wrapped object to file"); return YHR_GENERIC_ERROR; } return YHR_SUCCESS; } int yh_com_get_rsa_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { return do_rsa_wrap(ctx, argv, in_fmt, fmt, false); } int yh_com_get_rsa_wrapped_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { return do_rsa_wrap(ctx, argv, in_fmt, fmt, true); } // NOTE(adma): Get a template object // argc = 2 // arg 0: e:session, // arg 1: w:object_id int yh_com_get_template(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { uint8_t response[YH_MSG_BUF_SIZE]; size_t response_len = sizeof(response); UNUSED(in_fmt); yh_rc yrc = yh_util_get_template(argv[0].e, argv[1].w, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get template object: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE(adma): No operation command // argc = 0 int yh_com_noop(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); return 0; } // NOTE(adma): List capabilities // argc = 0 int yh_com_list_capabilities(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); for (size_t i = 0; i < sizeof(yh_capability) / sizeof(yh_capability[0]); i++) { fprintf(ctx->out, "%-30s (%016llx)\n", yh_capability[i].name, 1ULL << yh_capability[i].bit); } return 0; } // NOTE: List algorithms // argc = 0 int yh_com_list_algorithms(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); for (size_t i = 0; i < sizeof(yh_algorithms) / sizeof(yh_algorithms[0]); i++) { fprintf(ctx->out, "%s\n", yh_algorithms[i].name); } return 0; } // NOTE: List types // argc = 0 int yh_com_list_types(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); for (uint16_t i = 0; i < sizeof(yh_types) / sizeof(yh_types[0]); i++) { fprintf(ctx->out, "%s\n", yh_types[i].name); } return 0; } // NOTE(adma): List sessions // argc = 0 int yh_com_list_sessions(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); if (ctx->connector == NULL) { fprintf(stderr, "Not connected\n"); return -1; } for (size_t i = 0; i < sizeof(ctx->sessions) / sizeof(ctx->sessions[0]); i++) { if (ctx->sessions[i] != NULL) { fprintf(stderr, "Session %zu\n", i); } } return 0; } static int compare_objects(const void *p1, const void *p2) { const yh_object_descriptor *a = p1; const yh_object_descriptor *b = p2; return a->id - b->id; } // NOTE: List object according to a filter // argc = 7 // arg 0: e:session // arg 1: w:id // arg 2: t:type // arg 3: w:domains // arg 4: u:capabilities // arg 5: a:algorithm // arg 6: s:label int yh_com_list_objects(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { yh_object_descriptor objects[YH_MAX_ITEMS_COUNT] = {0}; size_t num_objects = YH_MAX_ITEMS_COUNT; const char *label_arg = 0; UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); if (argv[6].len == 0) { label_arg = NULL; } else { label_arg = argv[6].s; } yh_rc yrc = yh_util_list_objects(argv[0].e, argv[1].w, argv[2].b, argv[3].w, &argv[4].c, argv[5].a, label_arg, objects, &num_objects); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to list objects: %s\n", yh_strerror(yrc)); return -1; } qsort(objects, num_objects, sizeof(yh_object_descriptor), compare_objects); fprintf(ctx->out, "Found %zu object(s)\n", num_objects); for (size_t i = 0; i < num_objects; i++) { yrc = yh_util_get_object_info(argv[0].e, objects[i].id, objects[i].type, &objects[i]); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get object info: %s\n", yh_strerror(yrc)); return -1; } const char *type = ""; yh_type_to_string(objects[i].type, &type); const char *algo = ""; yh_algo_to_string(objects[i].algorithm, &algo); fprintf(ctx->out, "id: 0x%04x, type: %s, algo: %s, sequence: %hhu, label: %s\n", objects[i].id, type, algo, objects[i].sequence, objects[i].label); } return 0; } // NOTE(adma): Open a session with a connector using an Authentication Key // argc = 2 // arg 0: w:authkey // arg 1: i:password int yh_com_open_session(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); if (ctx->connector == NULL) { fprintf(stderr, "Not connected\n"); return -1; } yh_session *ses = NULL; yh_rc yrc = YHR_SUCCESS; if (in_fmt == fmt_password) { yrc = yh_create_session_derived(ctx->connector, argv[0].w, argv[1].x, argv[1].len, false, &ses); } else { yrc = yh_create_session(ctx->connector, argv[0].w, argv[1].x, argv[1].len / 2, argv[1].x + argv[1].len / 2, argv[1].len / 2, false, &ses); } insecure_memzero(argv[1].x, argv[1].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to create session: %s\n", yh_strerror(yrc)); return -1; } uint8_t session_id = 0; yrc = yh_get_session_id(ses, &session_id); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get session id: %s\n", yh_strerror(yrc)); return -1; } if (ctx->sessions[session_id] != NULL) { yrc = yh_destroy_session(&ctx->sessions[session_id]); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to destroy old session with same id (%d): %s\n", session_id, yh_strerror(yrc)); return -1; } } ctx->sessions[session_id] = ses; fprintf(stderr, "Created session %d\n", session_id); return 0; } // NOTE: Open a session with a connector using an Asymmetric // Authentication Key argc = 2 arg 0: w:authkey arg 1: i:password int yh_com_open_session_asym(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(fmt); if (ctx->connector == NULL) { fprintf(stderr, "Not connected\n"); return -1; } uint16_t authkey = argv[0].w; uint8_t privkey[YH_EC_P256_PRIVKEY_LEN] = {0}; yh_rc yrc = YHR_SUCCESS; if (in_fmt == fmt_password) { uint8_t pubkey[YH_EC_P256_PUBKEY_LEN] = {0}; yrc = yh_util_derive_ec_p256_key(argv[1].x, argv[1].len, privkey, sizeof(privkey), pubkey, sizeof(pubkey)); insecure_memzero(argv[1].x, argv[1].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to derive asymmetric authentication key: %s\n", yh_strerror(yrc)); return -1; } } else if (in_fmt == fmt_PEM) { yh_algorithm algo; size_t len = sizeof(privkey); if (!read_private_key(argv[1].x, argv[1].len, &algo, privkey, &len, false)) { fprintf(stderr, "Failed to PEM decode asymmetric authentication key\n"); return -1; } if (len != sizeof(privkey)) { fprintf(stderr, "Invalid asymmetric authentication key\n"); return -1; } } else if (argv[1].len <= sizeof(privkey)) { memset(privkey, 0, sizeof(privkey) - argv[1].len); memcpy(privkey + sizeof(privkey) - argv[1].len, argv[1].x, argv[1].len); insecure_memzero(argv[1].x, argv[1].len); } else { insecure_memzero(argv[1].x, argv[1].len); fprintf(stderr, "Invalid asymmetric authkey: %s\n", yh_strerror(YHR_INVALID_PARAMETERS)); return -1; } uint8_t device_pubkey[YH_EC_P256_PUBKEY_LEN] = {0}; size_t device_pubkey_len = sizeof(device_pubkey); yrc = yh_util_get_device_pubkey(ctx->connector, device_pubkey, &device_pubkey_len, NULL); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to retrieve device pubkey: %s\n", yh_strerror(yrc)); return -1; } if (device_pubkey_len != YH_EC_P256_PUBKEY_LEN) { fprintf(stderr, "Invalid device pubkey\n"); return -1; } int matched = 0; for (uint8_t **pubkey = ctx->device_pubkey_list; *pubkey; pubkey++) { if (!memcmp(*pubkey, device_pubkey, device_pubkey_len)) { matched++; break; } } if (ctx->device_pubkey_list[0] == NULL) { fprintf(stderr, "CAUTION: Device public key (PK.SD) not validated\n"); for (size_t i = 0; i < device_pubkey_len; i++) fprintf(stderr, "%02x", device_pubkey[i]); fprintf(stderr, "\n"); } else if (matched == 0) { fprintf(stderr, "Failed to validate device pubkey\n"); return -1; } yh_session *ses = NULL; yrc = yh_create_session_asym(ctx->connector, authkey, privkey, sizeof(privkey), device_pubkey, device_pubkey_len, &ses); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to create session: %s\n", yh_strerror(yrc)); return -1; } uint8_t session_id = 0; yrc = yh_get_session_id(ses, &session_id); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get session id: %s\n", yh_strerror(yrc)); return -1; } if (ctx->sessions[session_id] != NULL) { yrc = yh_destroy_session(&ctx->sessions[session_id]); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to destroy old session with same id (%d): %s\n", session_id, yh_strerror(yrc)); return -1; } } ctx->sessions[session_id] = ses; fprintf(stderr, "Created session %d\n", session_id); return 0; } // NOTE: Open a session using a key stored on YubiKey // argc = 3 // arg 0: w:authkey // arg 1: s:name // arg 2: i:password // arg 3: s:reader int yh_com_open_yksession(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); if (ctx->connector == NULL) { fprintf(stderr, "Not connected\n"); return -1; } ykhsmauth_rc ykhsmauthrc = ykhsmauth_connect(ctx->state, argv[3].s); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Failed to connect to the YubiKey: %s\n", ykhsmauth_strerror(ykhsmauthrc)); return -1; } uint8_t host_challenge[YH_EC_P256_PUBKEY_LEN] = {0}; size_t host_challenge_len = sizeof(host_challenge); uint8_t major = 0, minor = 0, patch = 0; ykhsmauthrc = ykhsmauth_get_version_ex(ctx->state, &major, &minor, &patch); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Failed to get YubiKey firmware version: %s\n", ykhsmauth_strerror(ykhsmauthrc)); ykhsmauth_disconnect(ctx->state); return -1; } if (major > 5 || (major == 5 && minor > 7) || (major == 5 && minor == 7 && patch >= 1)) { ykhsmauthrc = ykhsmauth_get_challenge_ex(ctx->state, argv[1].s, argv[2].x, argv[2].len, host_challenge, &host_challenge_len); } else { ykhsmauthrc = ykhsmauth_get_challenge(ctx->state, argv[1].s, host_challenge, &host_challenge_len); } if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Failed to get host challenge from the YubiKey: %s\n", ykhsmauth_strerror(ykhsmauthrc)); ykhsmauth_disconnect(ctx->state); return -1; } uint8_t card_pubkey[YH_EC_P256_PUBKEY_LEN] = {0}; size_t card_pubkey_len = 0; yh_rc yrc = YHR_SUCCESS; if (host_challenge_len == YH_EC_P256_PUBKEY_LEN) { card_pubkey_len = sizeof(card_pubkey); yrc = yh_util_get_device_pubkey(ctx->connector, card_pubkey, &card_pubkey_len, NULL); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to retrieve device pubkey: %s\n", yh_strerror(yrc)); ykhsmauth_disconnect(ctx->state); return -1; } if (card_pubkey_len != YH_EC_P256_PUBKEY_LEN) { fprintf(stderr, "Invalid device pubkey\n"); ykhsmauth_disconnect(ctx->state); return -1; } int matched = 0; for (uint8_t **pubkey = ctx->device_pubkey_list; *pubkey; pubkey++) { if (!memcmp(*pubkey, card_pubkey, card_pubkey_len)) { matched++; break; } } if (ctx->device_pubkey_list[0] == NULL) { fprintf(stderr, "CAUTION: Device public key (PK.SD) not validated\n"); for (size_t i = 0; i < card_pubkey_len; i++) fprintf(stderr, "%02x", card_pubkey[i]); fprintf(stderr, "\n"); } else if (matched == 0) { fprintf(stderr, "Failed to validate device pubkey\n"); ykhsmauth_disconnect(ctx->state); return -1; } } uint8_t card_cryptogram[YH_KEY_LEN] = {0}; size_t card_cryptogram_len = sizeof(card_cryptogram); uint8_t *yh_context = 0; yh_session *ses = NULL; yrc = yh_begin_create_session(ctx->connector, argv[0].w, &yh_context, host_challenge, &host_challenge_len, card_cryptogram, &card_cryptogram_len, &ses); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to create session: %s\n", yh_strerror(yrc)); ykhsmauth_disconnect(ctx->state); return -1; } uint8_t key_s_enc[YH_KEY_LEN] = {0}; uint8_t key_s_mac[YH_KEY_LEN] = {0}; uint8_t key_s_rmac[YH_KEY_LEN] = {0}; uint8_t retries = 0; ykhsmauthrc = ykhsmauth_calculate_ex(ctx->state, argv[1].s, yh_context, 2 * host_challenge_len, card_pubkey, card_pubkey_len, card_cryptogram, card_cryptogram_len, argv[2].x, argv[2].len, key_s_enc, sizeof(key_s_enc), key_s_mac, sizeof(key_s_mac), key_s_rmac, sizeof(key_s_rmac), &retries); insecure_memzero(argv[2].x, argv[2].len); ykhsmauth_disconnect(ctx->state); if (ykhsmauthrc != YKHSMAUTHR_SUCCESS) { fprintf(stderr, "Failed to get session keys from the YubiKey: %s", ykhsmauth_strerror(ykhsmauthrc)); if (ykhsmauthrc == YKHSMAUTHR_WRONG_PW) { fprintf(stderr, ", %d attempts remaining", retries); } fprintf(stderr, "\n"); return -1; } yrc = yh_finish_create_session(ses, key_s_enc, sizeof(key_s_enc), key_s_mac, sizeof(key_s_mac), key_s_rmac, sizeof(key_s_rmac), card_cryptogram, card_cryptogram_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to create session: %s\n", yh_strerror(yrc)); return -1; } uint8_t session_id = 0; yrc = yh_get_session_id(ses, &session_id); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to create session: %s\n", yh_strerror(yrc)); return -1; } if (ctx->sessions[session_id] != NULL) { yrc = yh_destroy_session(&ctx->sessions[session_id]); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to destroy old session with same id (%d): %s\n", session_id, yh_strerror(yrc)); return -1; } } ctx->sessions[session_id] = ses; fprintf(stderr, "Created session %d\n", session_id); return 0; } // NOTE(adma): Send unauthenticated echo // argc = 2 // arg 0: b:byte // arg 1: w:count int yh_com_pecho(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); uint8_t data[YH_MSG_BUF_SIZE] = {0}; uint16_t data_len = 0; uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = 0; yh_cmd response_cmd = 0; if (ctx->connector == NULL) { fprintf(stderr, "Not connected\n"); return -1; } uint8_t byte = argv[0].b; uint16_t count = argv[1].w; if (count > YH_MSG_BUF_SIZE) { fprintf(stderr, "Count must be in [0, %d]\n", YH_MSG_BUF_SIZE); return -1; } memset(data, byte, count); data_len = count; response_len = sizeof(response); yh_rc yrc = yh_send_plain_msg(ctx->connector, YHC_ECHO, data, data_len, &response_cmd, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to send ECHO command: %s\n", yh_strerror(yrc)); return -1; } fprintf(ctx->out, "Response (%zu bytes):\n", response_len); for (size_t i = 0; i < response_len; i++) { if (i && !(i % 64)) fprintf(ctx->out, "\n"); else if (i && !(i % 8)) fprintf(ctx->out, " "); fprintf(ctx->out, "%02x", response[i]); } fprintf(ctx->out, "\n"); return 0; } // Store a symmetric key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm // arg 6: i:key int yh_com_put_symmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc; if (yh_is_aes(argv[5].a)) { if ((argv[5].a == YH_ALGO_AES128 && argv[6].len != 16) || (argv[5].a == YH_ALGO_AES192 && argv[6].len != 24) || (argv[5].a == YH_ALGO_AES256 && argv[6].len != 32)) { fprintf(stderr, "Key length (%zu) not matching, should be 16, 24 or 32\n", argv[6].len); return -1; } yrc = yh_util_import_aes_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a, argv[6].x); } else { fprintf(stderr, "Invalid algorithm\n"); return -1; } if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store symmetric key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored symmetric key 0x%04x\n", argv[1].w); return 0; } // NOTE(adma): Store an asymmetric key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: x:key int yh_com_put_asymmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); uint8_t key[512] = {0}; size_t key_material_len = sizeof(key); yh_algorithm algorithm = 0; bool ret = read_private_key(argv[5].x, argv[5].len, &algorithm, key, &key_material_len, false); if (ret == false) { fprintf(stderr, "Unable to read asymmetric key\n"); return -1; } yh_rc yrc = YHR_SUCCESS; switch (algorithm) { case YH_ALGO_RSA_2048: case YH_ALGO_RSA_3072: case YH_ALGO_RSA_4096: yrc = yh_util_import_rsa_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, algorithm, key, key + key_material_len / 2); break; case YH_ALGO_EC_P224: case YH_ALGO_EC_P256: case YH_ALGO_EC_P384: case YH_ALGO_EC_P521: case YH_ALGO_EC_K256: case YH_ALGO_EC_BP256: case YH_ALGO_EC_BP384: case YH_ALGO_EC_BP512: yrc = yh_util_import_ec_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, algorithm, key); break; case YH_ALGO_EC_ED25519: yrc = yh_util_import_ed_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, algorithm, key); break; default: fprintf(stderr, "Unsupported algorithm\n"); return -1; } if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store asymmetric key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored Asymmetric key 0x%04x\n", argv[1].w); return 0; } // NOTE(adma): Store an authentication key // argc = 7 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: c:delegated_capabilities // arg 6: x:password int yh_com_put_authentication(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_import_authentication_key_derived(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, &argv[5].c, argv[6].x, argv[6].len); insecure_memzero(argv[6].x, argv[6].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store authkey: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored Authentication key 0x%04x\n", argv[1].w); return 0; } // NOTE: Store an asymmetric authentication key // argc = 7 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: c:delegated_capabilities // arg 6: x:password int yh_com_put_authentication_asym(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(fmt); yh_rc yrc = YHR_SUCCESS; uint8_t pubkey[YH_EC_P256_PUBKEY_LEN] = {0}; if (in_fmt == fmt_password) { uint8_t privkey[YH_EC_P256_PRIVKEY_LEN] = {0}; yrc = yh_util_derive_ec_p256_key(argv[6].x, argv[6].len, privkey, sizeof(privkey), pubkey, sizeof(pubkey)); insecure_memzero(argv[6].x, argv[6].len); insecure_memzero(privkey, sizeof(privkey)); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to derive asymmetric authentication key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Derived public key (PK.OCE)\n"); for (size_t i = 0; i < sizeof(pubkey); i++) fprintf(stderr, "%02x", pubkey[i]); fprintf(stderr, "\n"); } else if (in_fmt == fmt_PEM) { yh_algorithm algo = 0; size_t pubkey_len = sizeof(pubkey); if (!read_public_key(argv[6].x, argv[6].len, &algo, pubkey, &pubkey_len)) { fprintf(stderr, "Failed to load public key\n"); return -1; } if (pubkey_len != sizeof(pubkey)) { fprintf(stderr, "Invalid public key\n"); return -1; } } else if (argv[6].len <= sizeof(pubkey)) { memset(pubkey, 0, sizeof(pubkey) - argv[6].len); memcpy(pubkey + sizeof(pubkey) - argv[6].len, argv[6].x, argv[6].len); } else { fprintf(stderr, "Invalid asymmetric authkey: %s\n", yh_strerror(YHR_INVALID_PARAMETERS)); return -1; } yrc = yh_util_import_authentication_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, &argv[5].c, pubkey + 1, sizeof(pubkey) - 1, NULL, 0); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store asymmetric authkey: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored Asymmetric Authentication key 0x%04x\n", argv[1].w); return 0; } // NOTE(adma): Store an opaque object // argc = 6 // arg 0: e:session // arg 1: w:object_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm // arg 6: i:datafile int yh_com_put_opaque(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(fmt); unsigned char buf[YH_MSG_BUF_SIZE], *data = argv[6].x; size_t len = argv[6].len; if (in_fmt == fmt_PEM) { // Decode X.509 Certificate regardless of algorithm in case fmt_PEM is // explicitly set BIO *bio = BIO_new_mem_buf(data, len); if (!bio) { fprintf(stderr, "Couldn't wrap PEM-encoded certificate data\n"); return 0; } X509 *cert = PEM_read_bio_X509(bio, NULL, NULL, NULL); if (!cert) { fprintf(stderr, "Couldn't parse PEM-encoded certificate\n"); BIO_free(bio); return 0; } BIO_free(bio); len = i2d_X509(cert, 0); if (len > sizeof(buf)) { fprintf(stderr, "Decoded certificate is too large: %zu\n", len); X509_free(cert); return 0; } data = buf; i2d_X509(cert, &data); data = buf; X509_free(cert); } else if (argv[5].a == YH_ALGO_OPAQUE_X509_CERTIFICATE) { // Enforce valid X.509 certificate const unsigned char *p = data; X509 *cert = d2i_X509(NULL, &p, len); if (!cert) { fprintf(stderr, "Couldn't parse DER-encoded certificate\n"); return 0; } X509_free(cert); } yh_rc yrc = yh_util_import_opaque(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a, data, len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store opaque object: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored %zu bytes to Opaque object 0x%04x\n", len, argv[1].w); return 0; } // NOTE(adma): Set a global option value // argc = 3 // arg 0: e:session // arg 1: o:option // arg 2: x:value int yh_com_put_option(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_set_option(argv[0].e, argv[1].o, argv[2].len, argv[2].x); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store option: %s\n", yh_strerror(yrc)); return -1; } return 0; } // NOTE: Put a HMAC key // argc = 7 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm // arg 6: x:key int yh_com_put_hmac(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); if (argv[6].len > 128) { fprintf(stderr, "Too long key supplied, max 128 bytes allowed\n"); return -1; } yh_rc yrc = yh_util_import_hmac_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a, argv[6].x, argv[6].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store HMAC key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored HMAC key 0x%04x\n", argv[1].w); return 0; } // NOTE: Store a wrapping key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: c:delegated_capabilities // arg 6: x:key int yh_com_put_wrapkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_algorithm algo = 0; if (argv[6].len == 16) { algo = YH_ALGO_AES128_CCM_WRAP; } else if (argv[6].len == 24) { algo = YH_ALGO_AES192_CCM_WRAP; } else if (argv[6].len == 32) { algo = YH_ALGO_AES256_CCM_WRAP; } else { fprintf(stderr, "Key length not matching, should be 16, 24 or 32\n"); return -1; } yh_rc yrc = yh_util_import_wrap_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, algo, &argv[5].c, argv[6].x, argv[6].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store wrapkey: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored Wrap key 0x%04x\n", argv[1].w); return 0; } // NOTE: Store an RSA wrapping key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: c:delegated_capabilities // arg 6: x:key int yh_com_put_rsa_wrapkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); uint8_t key[512] = {0}; size_t key_material_len = sizeof(key); yh_algorithm algo = 0; bool ret = read_private_key(argv[6].x, argv[6].len, &algo, key, &key_material_len, false); if (ret == false) { fprintf(stderr, "Unable to read wrap key\n"); return -1; } yh_rc yrc = yh_util_import_wrap_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, algo, &argv[5].c, key, key_material_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store wrapkey: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored Wrap key 0x%04x\n", argv[1].w); return 0; } static bool read_rsa_pubkey(const uint8_t *buf, size_t len, uint8_t *bytes, size_t *bytes_len) { BIO *bio; if ((bio = BIO_new(BIO_s_mem())) == NULL) return false; (void) BIO_write(bio, buf, len); RSA *rsa = NULL; EVP_PKEY *pubkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); BIO_free_all(bio); if (pubkey == NULL || EVP_PKEY_base_id(pubkey) != EVP_PKEY_RSA || (rsa = EVP_PKEY_get1_RSA(pubkey)) == NULL) { fprintf(stderr, "Failed to parse RSA public key\n"); EVP_PKEY_free(pubkey); return false; } bool ret = false; const BIGNUM *n = NULL; RSA_get0_key(rsa, &n, NULL, NULL); if (n == NULL) { goto fail; } size_t nn = BN_num_bytes(n); if (*bytes_len < nn) { fprintf(stderr, "%s: insufficient dst buffer space\n", __func__); goto fail; } *bytes_len = (size_t) BN_bn2bin(n, bytes); ret = true; fail: RSA_free(rsa); EVP_PKEY_free(pubkey); return ret; } // NOTE: Store a public wrap key // argc = 6 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: c:delegated_capabilities // arg 6: i:pubkey int yh_com_put_public_wrapkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); uint8_t pubkey[512]; size_t pubkey_len = sizeof(pubkey); yh_algorithm algo = 0; if (!read_rsa_pubkey(argv[6].x, argv[6].len, pubkey, &pubkey_len)) { fprintf(stderr, "Failed to read public key\n"); return -1; } switch (pubkey_len) { case 256: algo = YH_ALGO_RSA_2048; break; case 384: algo = YH_ALGO_RSA_3072; break; case 512: algo = YH_ALGO_RSA_4096; break; default: fprintf(stderr, "Invalid public key length (%zu)\n", pubkey_len); return -1; } yh_rc yrc = yh_util_import_public_wrap_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, algo, &argv[5].c, pubkey, pubkey_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store public wrap key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored public wrap key 0x%04x\n", argv[1].w); return 0; } // NOTE: Store a wrapped object // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:data int yh_com_put_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_object_type object_type = 0; uint16_t object_id = 0; yh_rc yrc = yh_util_import_wrapped(argv[0].e, argv[1].w, argv[2].x, argv[2].len, &object_type, &object_id); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store wrapped object: %s\n", yh_strerror(yrc)); return -1; } const char *type = ""; yh_type_to_string(object_type, &type); fprintf(stderr, "Object imported as 0x%04x of type %s\n", object_id, type); return 0; } // NOTE: Store an asymetrically wrapped object // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: a:oaep // arg 3: a:mgf1 // arg 4: i:data int yh_com_put_rsa_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_object_type object_type = 0; uint16_t object_id = 0; yh_algorithm mgf1 = argv[3].a; yh_algorithm oaep = argv[2].a; int hash = 0; switch (oaep) { case YH_ALGO_RSA_OAEP_SHA1: hash = _SHA1; break; case YH_ALGO_RSA_OAEP_SHA256: hash = _SHA256; break; case YH_ALGO_RSA_OAEP_SHA384: hash = _SHA384; break; case YH_ALGO_RSA_OAEP_SHA512: hash = _SHA512; break; default: fprintf(stderr, "Unrecognized OAEP algorithm\n"); return -1; } uint8_t label[64] = {0}; size_t label_len = sizeof(label); if (hash_bytes(NULL, 0, hash, label, &label_len) == false) { fprintf(stderr, "Unable to hash data.\n"); return -1; } yh_rc yrc = yh_util_import_rsa_wrapped(argv[0].e, argv[1].w, oaep, mgf1, label, label_len, argv[4].x, argv[4].len, &object_type, &object_id); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store wrapped object: %s\n", yh_strerror(yrc)); return -1; } const char *type = ""; yh_type_to_string(object_type, &type); fprintf(stderr, "Object imported as 0x%04x of type %s\n", object_id, type); return 0; } // NOTE: Store an asymetrically wrapped key object // argc = 3 // arg 0: e:session // arg 1: w:wrapkey_id // arg 2: t:type // arg 3: w:key_id // arg 4: a:key_algorithm // arg 5: s:label // arg 6: w:domains // arg 7: c:capabilities // arg 8: a:oaep // arg 9: a:mgf1 // arg 10: i:data int yh_com_put_rsa_wrapped_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_object_type object_type = argv[2].t; uint16_t object_id = argv[3].w; yh_algorithm mgf1 = argv[9].a; yh_algorithm oaep = argv[8].a; int hash = 0; switch (oaep) { case YH_ALGO_RSA_OAEP_SHA1: hash = _SHA1; break; case YH_ALGO_RSA_OAEP_SHA256: hash = _SHA256; break; case YH_ALGO_RSA_OAEP_SHA384: hash = _SHA384; break; case YH_ALGO_RSA_OAEP_SHA512: hash = _SHA512; break; default: fprintf(stderr, "Unrecognized OAEP algorithm\n"); return -1; } uint8_t label[64] = {0}; size_t label_len = sizeof(label); if (hash_bytes(NULL, 0, hash, label, &label_len) == false) { fprintf(stderr, "Unable to hash data\n"); return -1; } yh_rc yrc = yh_util_put_rsa_wrapped_key(argv[0].e, argv[1].w, object_type, &object_id, argv[4].a, argv[5].s, argv[6].w, &argv[7].c, oaep, mgf1, label, label_len, argv[10].x, argv[10].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store wrapped object: %s\n", yh_strerror(yrc)); return -1; } const char *type = ""; yh_type_to_string(object_type, &type); fprintf(stderr, "Object imported as 0x%04x of type %s\n", object_id, type); return 0; } // NOTE(adma): Store a template object // argc = 7 // arg 0: e:session // arg 1: w:object_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm // arg 6: i:datafile int yh_com_put_template(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_import_template(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a, argv[6].x, argv[6].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store template object: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored Template object 0x%04x\n", argv[1].w); return 0; } // NOTE(adma): Sign data using ECDSA // argc = 4 // arg 0: e:session // arg 1: w:key_id // arg 2: a:algorithm // arg 3: i:datafile int yh_com_sign_ecdsa(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t data[YH_MSG_BUF_SIZE] = {0}; size_t data_len = sizeof(data); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); int hash = 0; switch (argv[2].a) { case YH_ALGO_EC_ECDSA_SHA1: hash = _SHA1; break; case YH_ALGO_EC_ECDSA_SHA256: hash = _SHA256; break; case YH_ALGO_EC_ECDSA_SHA384: hash = _SHA384; break; case YH_ALGO_EC_ECDSA_SHA512: hash = _SHA512; break; default: fprintf(stderr, "Invalid hash algorithm\n"); return -1; } if (hash_bytes(argv[3].x, argv[3].len, hash, data, &data_len) == false) { fprintf(stderr, "Unable to hash file\n"); return -1; } yh_rc yrc = yh_util_sign_ecdsa(argv[0].e, argv[1].w, data, data_len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to sign data with ecdsa: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE(adma): Sign data using EDDSA // argc = 4 // arg 0: e:session // arg 1: w:key_id // arg 2: a:algorithm // arg 3: i:datafile int yh_com_sign_eddsa(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); if (argv[2].a != YH_ALGO_EC_ED25519) { fprintf(stderr, "Invalid algorithm\n"); return -1; } yh_rc yrc = yh_util_sign_eddsa(argv[0].e, argv[1].w, argv[3].x, argv[3].len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to sign data with eddsa: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE(adma): Sign data using RSASSA-PKCS#1v1.5 // argc = 4 // arg 0: e:session // arg 1: w:key_id // arg 2: a:algorithm // arg 3: f:datafile int yh_com_sign_pkcs1v1_5(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t data[YH_MSG_BUF_SIZE] = {0}; size_t data_len = sizeof(data); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); int hash = 0; switch (argv[2].a) { case YH_ALGO_RSA_PKCS1_SHA1: hash = _SHA1; break; case YH_ALGO_RSA_PKCS1_SHA256: hash = _SHA256; break; case YH_ALGO_RSA_PKCS1_SHA384: hash = _SHA384; break; case YH_ALGO_RSA_PKCS1_SHA512: hash = _SHA512; break; default: fprintf(stderr, "Invalid hash algorithm\n"); return -1; } if (hash_bytes(argv[3].x, argv[3].len, hash, data, &data_len) == false) { fprintf(stderr, "Unable to hash file\n"); return -1; } yh_rc yrc = yh_util_sign_pkcs1v1_5(argv[0].e, argv[1].w, true, data, data_len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to sign data with PKCS#1v1.5: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE(adma): Sign data using RSASSA-PSS // argc = 4 // arg 0: e:session // arg 1: w:key_id // arg 2: a:algorithm // arg 3: f:datafile int yh_com_sign_pss(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t data[YH_MSG_BUF_SIZE] = {0}; size_t data_len = sizeof(data); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); int hash = 0; yh_algorithm mgf = 0; switch (argv[2].a) { case YH_ALGO_RSA_PSS_SHA1: hash = _SHA1; mgf = YH_ALGO_MGF1_SHA1; break; case YH_ALGO_RSA_PSS_SHA256: hash = _SHA256; mgf = YH_ALGO_MGF1_SHA256; break; case YH_ALGO_RSA_PSS_SHA384: hash = _SHA384; mgf = YH_ALGO_MGF1_SHA384; break; case YH_ALGO_RSA_PSS_SHA512: hash = _SHA512; mgf = YH_ALGO_MGF1_SHA512; break; default: fprintf(stderr, "Invalid hash algorithm\n"); return -1; } if (hash_bytes(argv[3].x, argv[3].len, hash, data, &data_len) == false) { fprintf(stderr, "Unable to hash file\n"); return -1; } // NOTE(adma): Salt length always matches the length of the hash yh_rc yrc = yh_util_sign_pss(argv[0].e, argv[1].w, data, data_len, response, &response_len, data_len, mgf); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to sign data with PSS: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE(adma): Extract the version number, serial number and supported // algorithms // argc = 0 int yh_com_get_device_info(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(argv); UNUSED(in_fmt); UNUSED(fmt); if (ctx->connector == NULL) { fprintf(stderr, "Not connected\n"); return -1; } yh_device_info device_info = {0}; yh_rc yrc = yh_util_get_device_info_ex(ctx->connector, &device_info); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get device info: %s\n", yh_strerror(yrc)); return -1; } fprintf(ctx->out, "Version number:\t\t%hhu.%hhu.%hhu\n", device_info.major, device_info.minor, device_info.patch); fprintf(ctx->out, "Serial number:\t\t%u\n", device_info.serial); fprintf(ctx->out, "Log used:\t\t%d/%d\n", device_info.log_used, device_info.log_total); fprintf(ctx->out, "Supported algorithms:\t"); for (size_t i = 0; i < device_info.n_algorithms; i++) { const char *algo_str; yh_algo_to_string(device_info.algorithms[i], &algo_str); fprintf(ctx->out, "%s, ", algo_str); if ((i + 1) % 3 == 0 && i != 0) { fprintf(ctx->out, "\n\t\t\t"); } } fprintf(ctx->out, "\n"); char part_number[256] = {0}; size_t part_number_len = sizeof(part_number); yrc = yh_util_get_partnumber(ctx->connector, part_number, &part_number_len); if (yrc == YHR_SUCCESS && part_number_len > 0) { fprintf(ctx->out, "Part number:\t\t%s\n", part_number); } return 0; } // NOTE: HMAC data // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: x:data int yh_com_hmac(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_sign_hmac(argv[0].e, argv[1].w, argv[2].x, argv[2].len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to HMAC data: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Reset device // argc = 1 // arg 0: e:session int yh_com_reset(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_reset_device(argv[0].e); if (yrc != YHR_CONNECTOR_ERROR && yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to reset device: %s\n", yh_strerror(yrc)); return -1; } fprintf(ctx->out, "Device successfully reset\n"); return 0; } // NOTE: Delete an object // argc = 3 // arg 0: e:session // arg 1: w:id // arg 2: t:type int yh_com_delete(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_delete_object(argv[0].e, argv[1].w, argv[2].t); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to delete object: %s\n", yh_strerror(yrc)); return -1; } // TODO(adma): the order of the arguments should be changed to id and type return 0; } // NOTE(adma): Sign an SSH public key // argc = 4 // arg 0: e:session // arg 1: w:key_id // arg 2: w:template_id // arg 3: a:algorithm // arg 4: i:datafile int yh_com_sign_ssh_certificate(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); // TODO: respect output format uint8_t data[YH_MSG_BUF_SIZE + 1024] = {0}; size_t response_len = sizeof(data); if (argv[4].len != (4 + 256)) { // 4 bytes timestamp + 256 byte signature fprintf(stderr, "Failed to sign ssh certificate: %s\n", yh_strerror(YHR_BUFFER_TOO_SMALL)); return -1; } memcpy(data, argv[4].x, argv[4].len); response_len -= argv[4].len; yh_rc yrc = yh_util_sign_ssh_certificate(argv[0].e, argv[1].w, argv[2].w, argv[3].a, data, argv[4].len, data + argv[4].len, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to get certificate signature: %s\n", yh_strerror(yrc)); return -1; } BIO *b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { fprintf(stderr, "Failed to sign SSH certificate.\n"); return -1; } BIO *bio = BIO_new(BIO_s_mem()); if (bio == NULL) { fprintf(stderr, "Failed to sign SSH certificate.\n"); BIO_free_all(b64); return -1; } bio = BIO_push(b64, bio); BUF_MEM *bufferPtr = 0; (void) BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); (void) BIO_write(bio, data + 4 + 256, argv[4].len + response_len - 4 - 256); // TODO(adma): FIXME, unmagify (void) BIO_flush(bio); (void) BIO_get_mem_ptr(bio, &bufferPtr); const char *ssh_cert_str = "ssh-rsa-cert-v01@openssh.com "; // TODO(adma): ECDSA if (fwrite(ssh_cert_str, 1, strlen(ssh_cert_str), ctx->out) != strlen(ssh_cert_str) || ferror(ctx->out)) { fprintf(stderr, "Unable to write data to file\n"); return -1; } if (fwrite(bufferPtr->data, 1, bufferPtr->length, ctx->out) != bufferPtr->length || ferror(ctx->out)) { fprintf(stderr, "Unable to write data to file\n"); return -1; } if (fwrite("\n", 1, 1, ctx->out) != 1 || ferror(ctx->out)) { fprintf(stderr, "Unable to write data to file\n"); return -1; } (void) BIO_free_all(bio); // TODO: fix this leak. return 0; } static void time_elapsed(struct timeval *after, struct timeval *before, struct timeval *result) { result->tv_sec = after->tv_sec - before->tv_sec; result->tv_usec = after->tv_usec - before->tv_usec; if (result->tv_usec < 0) { result->tv_sec--; result->tv_usec += 1000000; } } static void time_add(struct timeval *a, struct timeval *b, struct timeval *result) { result->tv_sec = a->tv_sec + b->tv_sec; result->tv_usec = a->tv_usec + b->tv_usec; if (result->tv_usec >= 1000000) { result->tv_sec++; result->tv_usec -= 1000000; } } static void time_average(struct timeval *in, size_t num, struct timeval *result) { time_t remains = in->tv_sec % num; result->tv_sec = in->tv_sec / num; result->tv_usec = in->tv_usec / num; if (remains) { remains *= 1000000; result->tv_usec += remains / num; } } static double time_tps(struct timeval *in, size_t num) { double time = in->tv_sec + (double) in->tv_usec / 1000000; return num / time; } static bool time_less(struct timeval *a, struct timeval *b) { if (a->tv_sec < b->tv_sec) { return true; } else if (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec) { return true; } else { return false; } } static int compare_algorithm(const void *a, const void *b) { return (*(const yh_algorithm *) a - *(const yh_algorithm *) b); } static yh_algorithm *algorithm_search(yh_algorithm key, const yh_algorithm *arr, size_t count) { return bsearch(&key, arr, count, sizeof(key), compare_algorithm); } // NOTE: Run a set of benchmarks // argc = 3 // arg 0: e:session // arg 1: d:count // arg 2: w:key_id // arg 3: a:algorithm int yh_com_benchmark(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); struct { yh_algorithm algo; yh_algorithm algo2; uint16_t bytes; const char *special; } benchmarks[] = { {YH_ALGO_RSA_2048, YH_ALGO_RSA_PKCS1_SHA256, 32, ""}, {YH_ALGO_RSA_3072, YH_ALGO_RSA_PKCS1_SHA384, 48, ""}, {YH_ALGO_RSA_4096, YH_ALGO_RSA_PKCS1_SHA512, 64, ""}, {YH_ALGO_RSA_2048, YH_ALGO_RSA_PSS_SHA256, 32, ""}, {YH_ALGO_RSA_3072, YH_ALGO_RSA_PSS_SHA384, 48, ""}, {YH_ALGO_RSA_4096, YH_ALGO_RSA_PSS_SHA512, 64, ""}, {YH_ALGO_EC_P224, YH_ALGO_EC_ECDSA_SHA1, 20, ""}, {YH_ALGO_EC_P256, YH_ALGO_EC_ECDSA_SHA256, 32, ""}, {YH_ALGO_EC_P384, YH_ALGO_EC_ECDSA_SHA384, 48, ""}, {YH_ALGO_EC_P521, YH_ALGO_EC_ECDSA_SHA512, 66, ""}, {YH_ALGO_EC_K256, YH_ALGO_EC_ECDSA_SHA256, 32, ""}, {YH_ALGO_EC_BP256, YH_ALGO_EC_ECDSA_SHA256, 32, ""}, {YH_ALGO_EC_BP384, YH_ALGO_EC_ECDSA_SHA384, 48, ""}, {YH_ALGO_EC_BP512, YH_ALGO_EC_ECDSA_SHA512, 64, ""}, {YH_ALGO_EC_P224, YH_ALGO_EC_ECDH, 56, ""}, {YH_ALGO_EC_P256, YH_ALGO_EC_ECDH, 64, ""}, {YH_ALGO_EC_P384, YH_ALGO_EC_ECDH, 96, ""}, {YH_ALGO_EC_P521, YH_ALGO_EC_ECDH, 132, ""}, {YH_ALGO_EC_K256, YH_ALGO_EC_ECDH, 64, ""}, {YH_ALGO_EC_BP256, YH_ALGO_EC_ECDH, 64, ""}, {YH_ALGO_EC_BP384, YH_ALGO_EC_ECDH, 96, ""}, {YH_ALGO_EC_BP512, YH_ALGO_EC_ECDH, 128, ""}, {YH_ALGO_EC_ED25519, 0, 32, "32 bytes data"}, {YH_ALGO_EC_ED25519, 0, 64, "64 bytes data"}, {YH_ALGO_EC_ED25519, 0, 128, "128 bytes data"}, {YH_ALGO_EC_ED25519, 0, 256, "256 bytes data"}, {YH_ALGO_EC_ED25519, 0, 512, "512 bytes data"}, {YH_ALGO_EC_ED25519, 0, 1024, "1024 bytes data"}, {YH_ALGO_HMAC_SHA1, 0, 64, ""}, {YH_ALGO_HMAC_SHA256, 0, 64, ""}, {YH_ALGO_HMAC_SHA384, 0, 128, ""}, {YH_ALGO_HMAC_SHA512, 0, 128, ""}, {YH_ALGO_AES128_CCM_WRAP, 0, 0, ""}, {YH_ALGO_AES192_CCM_WRAP, 0, 0, ""}, {YH_ALGO_AES256_CCM_WRAP, 0, 0, ""}, {YH_ALGO_AES128_CCM_WRAP, 0, 128, "1024 bytes data"}, {YH_ALGO_AES192_CCM_WRAP, 0, 128, "1024 bytes data"}, {YH_ALGO_AES256_CCM_WRAP, 0, 128, "1024 bytes data"}, {YH_ALGO_AES128_YUBICO_OTP, 0, 0, ""}, {YH_ALGO_AES192_YUBICO_OTP, 0, 0, ""}, {YH_ALGO_AES256_YUBICO_OTP, 0, 0, ""}, {YH_ALGO_AES128, YH_ALGO_AES_ECB, 128, ""}, {YH_ALGO_AES192, YH_ALGO_AES_ECB, 128, ""}, {YH_ALGO_AES256, YH_ALGO_AES_ECB, 128, ""}, {YH_ALGO_AES128, YH_ALGO_AES_CBC, 128, ""}, {YH_ALGO_AES192, YH_ALGO_AES_CBC, 128, ""}, {YH_ALGO_AES256, YH_ALGO_AES_CBC, 128, ""}, {0, 0, 8, "Random 8 bytes"}, {0, 0, 16, "Random 16 bytes"}, {0, 0, 32, "Random 32 bytes"}, {0, 0, 64, "Random 64 bytes"}, {0, 0, 128, "Random 128 bytes"}, {0, 0, 256, "Random 256 bytes"}, {0, 0, 512, "Random 512 bytes"}, {0, 0, 1024, "Random 1024 bytes"}, {YH_ALGO_AES128_YUBICO_AUTHENTICATION, 0, 0, ""}, {YH_ALGO_EC_P256_YUBICO_AUTHENTICATION, 0, 0, ""}, }; // this is some data for the OTP benchmark const uint8_t otp_key[] = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f"; const uint8_t otp_id[] = "\x01\x02\x03\x04\x05\x06"; const uint8_t otp[] = "\x2f\x5d\x71\xa4\x91\x5d\xec\x30\x4a\xa1\x3c\xcf\x97\xbb\x0d\xbb"; const uint8_t password[] = "benchmark"; if (argv[1].d == 0) { fprintf(stderr, "Benchmark with 0 rounds seems pointless\n"); return -1; } yh_algorithm algorithms[YH_MAX_ALGORITHM_COUNT]; size_t n_algorithms = sizeof(algorithms) / sizeof(algorithms[0]); if (yh_util_get_device_info(ctx->connector, NULL, NULL, NULL, NULL, NULL, NULL, algorithms, &n_algorithms) != YHR_SUCCESS) { fprintf(stderr, "Could not fetch supported algorithms\n"); return -1; } for (size_t i = 0; i < sizeof(benchmarks) / sizeof(benchmarks[0]); i++) { struct timeval total = {0, 0}; struct timeval avg = {0, 0}; struct timeval max = {0, 0}; struct timeval min = {0, 0}; yh_capabilities capabilities = {{0}}; yh_rc yrc = YHR_SUCCESS; uint8_t algo_data[1024] = {0}; size_t algo_len = sizeof(algo_data); const char *str1 = NULL, *str2 = "", *str3 = ""; uint16_t id = argv[2].w; char label[YH_OBJ_LABEL_LEN + 1] = {0}; uint8_t sk_oce[YH_EC_P256_PRIVKEY_LEN], pk_oce[YH_EC_P256_PUBKEY_LEN], pk_sd[YH_EC_P256_PUBKEY_LEN]; size_t pk_sd_len = sizeof(pk_sd); yh_object_type type = 0; #ifndef _WIN32 size_t chars = 0; #endif if (argv[3].a != 0) { if (argv[3].a != benchmarks[i].algo && argv[3].a != benchmarks[i].algo2) { continue; } } if (benchmarks[i].algo) { yh_algo_to_string(benchmarks[i].algo, &str1); } if (benchmarks[i].algo2) { str2 = " "; yh_algo_to_string(benchmarks[i].algo2, &str3); } if (str1) { snprintf(label, YH_OBJ_LABEL_LEN, "Benchmark: %s%s%s", str1, str2, str3); } if ((benchmarks[i].algo && !algorithm_search(benchmarks[i].algo, algorithms, n_algorithms)) || (benchmarks[i].algo2 && !algorithm_search(benchmarks[i].algo2, algorithms, n_algorithms))) { fprintf(stderr, "%s%s%s skipped (disabled or unsupported)\n", str1, str2, str3); continue; } if (str1) { #ifndef _WIN32 chars = #endif fprintf(stderr, "Doing benchmark setup for %s%s%s...", str1, str2, str3); } if (yh_is_rsa(benchmarks[i].algo)) { if (benchmarks[i].algo2 == YH_ALGO_RSA_PKCS1_SHA256 || benchmarks[i].algo2 == YH_ALGO_RSA_PKCS1_SHA384 || benchmarks[i].algo2 == YH_ALGO_RSA_PKCS1_SHA512) { yh_string_to_capabilities("sign-pkcs", &capabilities); } else if (benchmarks[i].algo2 == YH_ALGO_RSA_PSS_SHA256 || benchmarks[i].algo2 == YH_ALGO_RSA_PSS_SHA384 || benchmarks[i].algo2 == YH_ALGO_RSA_PSS_SHA512) { yh_string_to_capabilities("sign-pss", &capabilities); } else { fprintf(stderr, "Unknown benchmark algorithms\n"); return -1; } type = YH_ASYMMETRIC_KEY; yrc = yh_util_generate_rsa_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo); } else if (yh_is_ec(benchmarks[i].algo)) { if (benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA1 || benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA256 || benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA384 || benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA512) { yh_string_to_capabilities("sign-ecdsa", &capabilities); } else if (benchmarks[i].algo2 == YH_ALGO_EC_ECDH) { yh_string_to_capabilities("derive-ecdh", &capabilities); yrc = yh_util_generate_ec_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed ECDH setup\n"); return -1; } algo_len--; yrc = yh_util_get_public_key_ex(argv[0].e, YH_ASYMMETRIC_KEY, id, algo_data + 1, &algo_len, NULL); if (yrc != YHR_SUCCESS || algo_len != benchmarks[i].bytes) { fprintf(stderr, "Failed to get ECDH pubkey (%zu)\n", algo_len); return -1; } algo_data[0] = 0x04; // this is a hack to make it look correct.. algo_len++; yrc = yh_util_delete_object(argv[0].e, id, YH_ASYMMETRIC_KEY); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed deleting temporary ec key\n"); return -1; } } else { fprintf(stderr, "Unknown benchmark algorithms\n"); return -1; } type = YH_ASYMMETRIC_KEY; yrc = yh_util_generate_ec_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo); } else if (benchmarks[i].algo == YH_ALGO_EC_ED25519) { yh_string_to_capabilities("sign-eddsa", &capabilities); type = YH_ASYMMETRIC_KEY; yrc = yh_util_generate_ed_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo); str2 = " "; str3 = benchmarks[i].special; } else if (yh_is_hmac(benchmarks[i].algo)) { type = YH_HMAC_KEY; yh_string_to_capabilities("sign-hmac", &capabilities); yrc = yh_util_generate_hmac_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo); } else if (benchmarks[i].algo == YH_ALGO_AES128_CCM_WRAP || benchmarks[i].algo == YH_ALGO_AES192_CCM_WRAP || benchmarks[i].algo == YH_ALGO_AES256_CCM_WRAP) { type = YH_WRAP_KEY; yh_string_to_capabilities( "export-wrapped,exportable-under-wrap,wrap-data", &capabilities); yrc = yh_util_generate_wrap_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo, &capabilities); if (benchmarks[i].bytes > 0) { str2 = " "; str3 = benchmarks[i].special; } } else if (benchmarks[i].algo == YH_ALGO_AES128_YUBICO_OTP || benchmarks[i].algo == YH_ALGO_AES192_YUBICO_OTP || benchmarks[i].algo == YH_ALGO_AES256_YUBICO_OTP) { type = YH_OTP_AEAD_KEY; yh_string_to_capabilities("decrypt-otp,create-otp-aead", &capabilities); yrc = yh_util_generate_otp_aead_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo, 0x12345678); if (yrc == YHR_SUCCESS) { yrc = yh_util_create_otp_aead(argv[0].e, id, otp_key, otp_id, algo_data, &algo_len); } } else if (yh_is_aes(benchmarks[i].algo)) { type = YH_SYMMETRIC_KEY; yh_string_to_capabilities( "decrypt-ecb,encrypt-ecb,decrypt-cbc,encrypt-cbc", &capabilities); yrc = yh_util_generate_aes_key(argv[0].e, &id, label, 0xffff, &capabilities, benchmarks[i].algo); } else if (strncmp(benchmarks[i].special, "Random ", 7) == 0) { str1 = benchmarks[i].special; } else if (benchmarks[i].algo == YH_ALGO_AES128_YUBICO_AUTHENTICATION) { type = YH_AUTHENTICATION_KEY; yh_string_to_capabilities("", &capabilities); yrc = yh_util_import_authentication_key_derived(argv[0].e, &id, label, 0xffff, &capabilities, &capabilities, password, sizeof(password) - 1); } else if (benchmarks[i].algo == YH_ALGO_EC_P256_YUBICO_AUTHENTICATION) { type = YH_AUTHENTICATION_KEY; yh_string_to_capabilities("", &capabilities); yrc = yh_util_generate_ec_p256_key(sk_oce, sizeof(sk_oce), pk_oce, sizeof(pk_oce)); if (yrc == YHR_SUCCESS) { yrc = yh_util_import_authentication_key(argv[0].e, &id, label, 0xffff, &capabilities, &capabilities, pk_oce + 1, sizeof(pk_oce) - 1, NULL, 0); if (yrc == YHR_SUCCESS) { pk_sd_len = sizeof(pk_sd); yrc = yh_util_get_device_pubkey(ctx->connector, pk_sd, &pk_sd_len, NULL); } } } else { fprintf(stderr, "Unknown benchmark algorithms\n"); return -1; } if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed benchmark setup for %s%s%s\n", str1, str2, str3); return -1; } memset(&min, 0x7f, sizeof(min)); for (uint32_t j = 0; j < argv[1].d; j++) { uint8_t data[1024]; uint8_t out[1024]; size_t out_len = sizeof(out); struct timeval before, after, result; memset(data, j, sizeof(data)); gettimeofday(&before, NULL); if (yh_is_rsa(benchmarks[i].algo) && (benchmarks[i].algo2 == YH_ALGO_RSA_PKCS1_SHA256 || benchmarks[i].algo2 == YH_ALGO_RSA_PKCS1_SHA384 || benchmarks[i].algo2 == YH_ALGO_RSA_PKCS1_SHA512)) { yrc = yh_util_sign_pkcs1v1_5(argv[0].e, id, true, data, benchmarks[i].bytes, out, &out_len); } else if (yh_is_rsa(benchmarks[i].algo) && (benchmarks[i].algo2 == YH_ALGO_RSA_PSS_SHA256 || benchmarks[i].algo2 == YH_ALGO_RSA_PSS_SHA384 || benchmarks[i].algo2 == YH_ALGO_RSA_PSS_SHA512)) { yrc = yh_util_sign_pss(argv[0].e, id, data, benchmarks[i].bytes, out, &out_len, benchmarks[i].bytes, YH_ALGO_MGF1_SHA1); } else if (yh_is_ec(benchmarks[i].algo) && (benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA1 || benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA256 || benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA384 || benchmarks[i].algo2 == YH_ALGO_EC_ECDSA_SHA512)) { yrc = yh_util_sign_ecdsa(argv[0].e, id, data, benchmarks[i].bytes, out, &out_len); } else if (yh_is_ec(benchmarks[i].algo) && benchmarks[i].algo2 == YH_ALGO_EC_ECDH) { yrc = yh_util_derive_ecdh(argv[0].e, id, algo_data, algo_len, out, &out_len); } else if (benchmarks[i].algo == YH_ALGO_EC_ED25519) { yrc = yh_util_sign_eddsa(argv[0].e, id, data, benchmarks[i].bytes, out, &out_len); } else if (yh_is_hmac(benchmarks[i].algo)) { yrc = yh_util_sign_hmac(argv[0].e, id, data, benchmarks[i].bytes, out, &out_len); } else if (benchmarks[i].bytes > 0 && (benchmarks[i].algo == YH_ALGO_AES128_CCM_WRAP || benchmarks[i].algo == YH_ALGO_AES192_CCM_WRAP || benchmarks[i].algo == YH_ALGO_AES256_CCM_WRAP)) { yrc = yh_util_wrap_data(argv[0].e, id, data, benchmarks[i].bytes, out, &out_len); } else if (benchmarks[i].algo == YH_ALGO_AES128_CCM_WRAP || benchmarks[i].algo == YH_ALGO_AES192_CCM_WRAP || benchmarks[i].algo == YH_ALGO_AES256_CCM_WRAP) { yrc = yh_util_export_wrapped(argv[0].e, id, YH_WRAP_KEY, id, out, &out_len); } else if (benchmarks[i].algo == YH_ALGO_AES128_YUBICO_OTP || benchmarks[i].algo == YH_ALGO_AES192_YUBICO_OTP || benchmarks[i].algo == YH_ALGO_AES256_YUBICO_OTP) { yrc = yh_util_decrypt_otp(argv[0].e, id, algo_data, algo_len, otp, NULL, NULL, NULL, NULL); } else if (yh_is_aes(benchmarks[i].algo)) { if (benchmarks[i].algo2 == YH_ALGO_AES_ECB) { yrc = yh_util_encrypt_aes_ecb(argv[0].e, id, data, benchmarks[i].bytes, out, &out_len); } else if (benchmarks[i].algo2 == YH_ALGO_AES_CBC) { yrc = yh_util_encrypt_aes_cbc(argv[0].e, id, data, data, benchmarks[i].bytes, out, &out_len); } else { fprintf(stderr, "Unknown benchmark algorithms\n"); return -1; } } else if (strncmp(benchmarks[i].special, "Random ", 7) == 0) { yrc = yh_util_get_pseudo_random(argv[0].e, benchmarks[i].bytes, out, &out_len); } else if (benchmarks[i].algo == YH_ALGO_AES128_YUBICO_AUTHENTICATION) { yh_session *ses = NULL; yrc = yh_create_session_derived(ctx->connector, id, password, sizeof(password) - 1, false, &ses); if (yrc == YHR_SUCCESS) { yrc = yh_util_close_session(ses); } } else if (benchmarks[i].algo == YH_ALGO_EC_P256_YUBICO_AUTHENTICATION) { yh_session *ses = NULL; yrc = yh_create_session_asym(ctx->connector, id, sk_oce, sizeof(sk_oce), pk_sd, pk_sd_len, &ses); if (yrc == YHR_SUCCESS) { yrc = yh_util_close_session(ses); } } else { fprintf(stderr, "Unknown benchmark algorithm\n"); return -1; } gettimeofday(&after, NULL); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed running benchmark %u for %s%s%s\n", j, str1, str2, str3); return -1; } time_elapsed(&after, &before, &result); if (time_less(&result, &min)) { min = result; } if (time_less(&max, &result)) { max = result; } time_add(&result, &total, &total); time_average(&total, j + 1, &avg); #ifndef _WIN32 struct winsize w; ioctl(fileno(stderr), TIOCGWINSZ, &w); if (chars > w.ws_col) { // move the cursor up and to column 1 fprintf(stderr, "\33[%zuF", chars / w.ws_col); } else { // if we're still on same line, just move to column 1 fprintf(stderr, "\33[1G"); } // clear display from cursor fprintf(stderr, "\33[J"); chars = fprintf(stderr, "%s%s%s (%u/%d times) total: %ld.%06ld avg: %ld.%06ld " "min: %ld.%06ld max: %ld.%06ld tps: %.06f", str1, str2, str3, j + 1, argv[1].w, total.tv_sec, (long) total.tv_usec, avg.tv_sec, (long) avg.tv_usec, min.tv_sec, (long) min.tv_usec, max.tv_sec, (long) max.tv_usec, time_tps(&total, j + 1)); fflush(stderr); #endif } #ifdef _WIN32 fprintf(stderr, "%s%s%s (%d times) total: %ld.%06ld avg: %ld.%06ld " "min: %ld.%06ld max: %ld.%06ld tps: %.06f", str1, str2, str3, argv[1].w, total.tv_sec, (long) total.tv_usec, avg.tv_sec, (long) avg.tv_usec, min.tv_sec, (long) min.tv_usec, max.tv_sec, (long) max.tv_usec, time_tps(&total, argv[1].w)); #endif fprintf(stderr, "\n"); if (type != 0) { yh_util_delete_object(argv[0].e, id, type); } } return 0; } // NOTE: create aead from OTP parameters // argc = 5 // arg 0: e:session // arg 1: w:key_id // arg 2: x:key // arg 3: x:private_id // arg 4: f:aead int yh_com_otp_aead_create(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); if (argv[2].len != 16) { fprintf(stderr, "Wrong length key supplied, has to be 16 bytes\n"); return -1; } if (argv[3].len != 6) { fprintf(stderr, "Wrong length id supplied, has to be 6 bytes\n"); return -1; } yh_rc yrc = yh_util_create_otp_aead(argv[0].e, argv[1].w, argv[2].x, argv[3].x, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to create OTP AEAD: %s\n", yh_strerror(yrc)); return -1; } if (write_file(response, response_len, ctx->out, fmt_to_fmt(fmt))) { return 0; } return -1; } // NOTE: create aead from OTP parameters // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: f:aead int yh_com_otp_aead_random(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_randomize_otp_aead(argv[0].e, argv[1].w, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to create OTP AEAD: %s\n", yh_strerror(yrc)); return -1; } if (write_file(response, response_len, ctx->out, fmt_to_fmt(fmt))) { return 0; } return -1; } // NOTE: decrypt OTP with AEAD // argc = 4 // arg 0: e:session // arg 1: w:key_id // arg 2: s:otp // arg 3: i:aead int yh_com_otp_decrypt(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); if (argv[2].len != 32) { fprintf(stderr, "Wrong length OTP supplied, has to be 16 bytes in hex\n"); return -1; } uint8_t otp[16] = {0}; size_t otp_len = sizeof(otp); if (hex_decode(argv[2].s, otp, &otp_len) == false) { fprintf(stderr, "Failed to decode OTP\n"); return -1; } uint16_t useCtr = 0; uint8_t sessionCtr = 0; uint8_t tstph = 0; uint16_t tstpl = 0; yh_rc yrc = yh_util_decrypt_otp(argv[0].e, argv[1].w, argv[3].x, argv[3].len, otp, &useCtr, &sessionCtr, &tstph, &tstpl); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to decrypt OTP: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "OTP decoded, useCtr:%d, sessionCtr:%d, tstph:%d, tstpl:%d\n", useCtr, sessionCtr, tstph, tstpl); return 0; } // NOTE: rewrap OTP AEAD to a different key // argc = 5 // arg 0: e:session // arg 1: w:id_from // arg 2: w:id_to // arg 3: i:aead_in // arg 4: F:aead_out int yh_com_otp_rewrap(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); UNUSED(ctx); UNUSED(in_fmt); yh_rc yrc = yh_util_rewrap_otp_aead(argv[0].e, argv[1].w, argv[2].w, argv[3].x, argv[3].len, response, &response_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to rewrap OTP AEAD: %s\n", yh_strerror(yrc)); return -1; } if (write_file(response, response_len, ctx->out, fmt_to_fmt(fmt))) { return 0; } return -1; } // NOTE: decrypt OTP with AEAD // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: 2:attest_id int yh_com_sign_attestation_certificate(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); uint8_t data[2048] = {0}; size_t data_len = sizeof(data); int ret = -1; yh_rc yrc = yh_util_sign_attestation_certificate(argv[0].e, argv[1].w, argv[2].w, data, &data_len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to attest asymmetric key: %s\n", yh_strerror(yrc)); return -1; } const unsigned char *ptr = data; X509 *x509 = d2i_X509(NULL, &ptr, data_len); if (!x509) { fprintf(stderr, "Failed parsing x509 information\n"); } else { if (fmt == fmt_base64 || fmt == fmt_PEM) { if (PEM_write_X509(ctx->out, x509) == 1) { ret = 0; } else { fprintf(stderr, "Failed writing x509 information\n"); } } else if (fmt == fmt_binary) { if (i2d_X509_fp(ctx->out, x509) == 1) { ret = 0; } else { fprintf(stderr, "Failed writing x509 information\n"); } } } X509_free(x509); return ret; } // NOTE: put OTP AEAD key // argc = 7 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: d:nonce_id // arg 6: x:key int yh_com_put_otp_aead_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); if (argv[6].len != 16 && argv[6].len != 24 && argv[6].len != 32) { fprintf(stderr, "Key length (%zu) not matching, should be 16, 24 or 32\n", argv[6].len); return -1; } yh_rc yrc = yh_util_import_otp_aead_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].d, argv[6].x, argv[6].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to store OTP AEAD key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Stored OTP AEAD key 0x%04x\n", argv[1].w); return 0; } // NOTE: generate OTP AEAD key // argc = 7 // arg 0: e:session // arg 1: w:key_id // arg 2: s:label // arg 3: w:domains // arg 4: c:capabilities // arg 5: a:algorithm // arg 6: d:nonce_id int yh_com_generate_otp_aead_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(ctx); UNUSED(in_fmt); UNUSED(fmt); yh_rc yrc = yh_util_generate_otp_aead_key(argv[0].e, &argv[1].w, argv[2].s, argv[3].w, &argv[4].c, argv[5].a, argv[6].d); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to generate OTP AEAD key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Generated OTP AEAD key 0x%04x\n", argv[1].w); return 0; } // NOTE(adma): Decrypt data using RSAES-OAEP // argc = 5 // arg 0: e:session // arg 1: w:key_id // arg 2: a:algorithm // arg 3: f:datafile // arg 4: s:label int yh_com_decrypt_oaep(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); int hash = 0; yh_algorithm mgf = 0; switch (argv[2].a) { case YH_ALGO_RSA_OAEP_SHA1: hash = _SHA1; mgf = YH_ALGO_MGF1_SHA1; break; case YH_ALGO_RSA_OAEP_SHA256: hash = _SHA256; mgf = YH_ALGO_MGF1_SHA256; break; case YH_ALGO_RSA_OAEP_SHA384: hash = _SHA384; mgf = YH_ALGO_MGF1_SHA384; break; case YH_ALGO_RSA_OAEP_SHA512: hash = _SHA512; mgf = YH_ALGO_MGF1_SHA512; break; default: fprintf(stderr, "Invalid hash algorithm\n"); return -1; } uint8_t label[64] = {0}; size_t label_len = sizeof(label); if (hash_bytes((const uint8_t *) argv[4].s, argv[4].len, hash, label, &label_len) == false) { fprintf(stderr, "Unable to hash data\n"); return -1; } uint8_t response[YH_MSG_BUF_SIZE] = {0}; size_t response_len = sizeof(response); yh_rc yrc = yh_util_decrypt_oaep(argv[0].e, argv[1].w, argv[3].x, argv[3].len, response, &response_len, label, label_len, mgf); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to decrypt data with OAEP: %s\n", yh_strerror(yrc)); return -1; } write_file(response, response_len, ctx->out, fmt_to_fmt(fmt)); return 0; } // NOTE: Set ca cert for https validation // argc = 1 // arg 0: s:filename int yh_com_set_cacert(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); if (ctx->cacert) { free(ctx->cacert); } ctx->cacert = strdup(argv[0].s); return 0; } // NOTE: Set https client cert // argc = 1 // arg 0: s:filename int yh_com_set_cert(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); if (ctx->cert) { free(ctx->cert); } ctx->cert = strdup(argv[0].s); return 0; } // NOTE: Set https client key // argc = 1 // arg 0: s:filename int yh_com_set_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); if (ctx->key) { free(ctx->key); } ctx->key = strdup(argv[0].s); return 0; } // NOTE: Set proxy server to use for connector // argc = 1 // arg 0: s:proxy int yh_com_set_proxy(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); if (ctx->proxy) { free(ctx->proxy); } ctx->proxy = strdup(argv[0].s); return 0; } // NOTE: Set noproxy list to use for connector // argc = 1 // arg 0: s:proxy int yh_com_set_noproxy(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); if (ctx->noproxy) { free(ctx->noproxy); } ctx->noproxy = strdup(argv[0].s); return 0; } // NOTE: Change authentication key // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:password int yh_com_change_authentication_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(in_fmt); UNUSED(fmt); UNUSED(ctx); yh_rc yrc = yh_util_change_authentication_key_derived(argv[0].e, &argv[1].w, argv[2].x, argv[2].len); insecure_memzero(argv[2].x, argv[2].len); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to change authentication key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Changed Authentication key 0x%04x\n", argv[1].w); return 0; } // NOTE: Change asymmetric authentication key // argc = 3 // arg 0: e:session // arg 1: w:key_id // arg 2: i:password int yh_com_change_authentication_key_asym(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt) { UNUSED(fmt); UNUSED(ctx); uint8_t pubkey[YH_EC_P256_PUBKEY_LEN] = {0}; yh_rc yrc = YHR_SUCCESS; if (in_fmt == fmt_password) { uint8_t privkey[YH_EC_P256_PRIVKEY_LEN]; yrc = yh_util_derive_ec_p256_key(argv[2].x, argv[2].len, privkey, sizeof(privkey), pubkey, sizeof(pubkey)); insecure_memzero(argv[2].x, argv[2].len); insecure_memzero(privkey, sizeof(privkey)); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to derive asymmetric authentication key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Derived public key (PK.OCE)\n"); for (size_t i = 0; i < sizeof(pubkey); i++) fprintf(stderr, "%02x", pubkey[i]); fprintf(stderr, "\n"); } else if (in_fmt == fmt_PEM) { yh_algorithm algo = 0; size_t pubkey_len = sizeof(pubkey); if (!read_public_key(argv[2].x, argv[2].len, &algo, pubkey, &pubkey_len)) { fprintf(stderr, "Failed to load public key\n"); return -1; } if (pubkey_len != sizeof(pubkey)) { fprintf(stderr, "Invalid public key\n"); return -1; } } else if (argv[2].len <= sizeof(pubkey)) { memset(pubkey, 0, sizeof(pubkey) - argv[2].len); memcpy(pubkey + sizeof(pubkey) - argv[2].len, argv[2].x, argv[2].len); } else { fprintf(stderr, "Invalid asymmetric authkey: %s\n", yh_strerror(YHR_INVALID_PARAMETERS)); return -1; } yrc = yh_util_change_authentication_key(argv[0].e, &argv[1].w, pubkey + 1, sizeof(pubkey) - 1, NULL, 0); if (yrc != YHR_SUCCESS) { fprintf(stderr, "Failed to change asymmetric authentication key: %s\n", yh_strerror(yrc)); return -1; } fprintf(stderr, "Changed Asymmetric Authentication key 0x%04x\n", argv[1].w); return 0; } yubihsm-shell-2.6.0/src/commands.h0000644000175100001770000002754214666527773016453 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef COMMANDS_H #define COMMANDS_H #include #include "yubihsm.h" #include "yubihsm-shell.h" typedef struct { union { uint8_t b; uint16_t w; uint32_t d; const char *s; yh_session *e; yh_capabilities c; yh_algorithm a; yh_object_type t; yh_option o; }; uint8_t *x; size_t len; } Argument; typedef int CommandFunction(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_audit(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_log_index(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_close_session(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_connect(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_debug_all(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_debug_error(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_debug_info(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_debug_intermediate(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_debug_none(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_debug_raw(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_debug_crypto(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_decrypt_pkcs1v1_5(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_decrypt_oaep(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_derive_ecdh(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_decrypt_aesccm(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_encrypt_aesccm(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_decrypt_aes_ecb(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_encrypt_aes_ecb(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_decrypt_aes_cbc(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_encrypt_aes_cbc(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_disconnect(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_echo(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_echo(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_generate_symmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_generate_asymmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_generate_hmac(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_generate_wrap(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_generate_otp_aead_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_opaque(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_option(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_random(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_storage(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_pubkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_device_pubkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_object_info(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_rsa_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_rsa_wrapped_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_device_info(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_get_template(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_list_capabilities(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_list_algorithms(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_list_types(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_list_connectors(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_list_sessions(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_list_objects(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_open_session(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_open_session_asym(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_open_yksession(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_pecho(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_symmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_asymmetric(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_authentication(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_authentication_asym(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_opaque(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_option(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_hmac(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_wrapkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_rsa_wrapkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_public_wrapkey(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_rsa_wrapped(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_rsa_wrapped_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_template(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_put_otp_aead_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_sign_ecdsa(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_sign_eddsa(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_sign_pkcs1v1_5(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_sign_pss(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_hmac(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_reset(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_delete(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_sign_ssh_certificate(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_benchmark(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_otp_aead_create(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_otp_aead_random(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_otp_decrypt(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_otp_rewrap(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_sign_attestation_certificate(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_keepalive_on(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_keepalive_off(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_noop(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_blink(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_cacert(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_cert(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_proxy(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_set_noproxy(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_change_authentication_key(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); int yh_com_change_authentication_key_asym(yubihsm_context *ctx, Argument *argv, cmd_format in_fmt, cmd_format fmt); #endif yubihsm-shell-2.6.0/src/cmdline.h0000644000175100001770000005743014666530034016244 0ustar runnerdocker/** @file cmdline.h * @brief The header file for the command line option parser * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten * @author GNU Gengetopt */ #ifndef CMDLINE_H #define CMDLINE_H /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* for FILE */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CMDLINE_PARSER_PACKAGE /** @brief the program name (used for printing errors) */ #define CMDLINE_PARSER_PACKAGE PACKAGE #endif #ifndef CMDLINE_PARSER_PACKAGE_NAME /** @brief the complete program name (used for help and version) */ #ifdef PACKAGE_NAME #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE_NAME #else #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE #endif #endif #ifndef CMDLINE_PARSER_VERSION /** @brief the program version */ #define CMDLINE_PARSER_VERSION VERSION #endif enum enum_action { action__NULL = -1, action_arg_benchmark = 0, action_arg_blinkMINUS_device, action_arg_createMINUS_otpMINUS_aead, action_arg_decryptMINUS_aesccm, action_arg_decryptMINUS_aescbc, action_arg_decryptMINUS_aesecb, action_arg_decryptMINUS_oaep, action_arg_decryptMINUS_otp, action_arg_decryptMINUS_pkcs1v15, action_arg_deleteMINUS_object, action_arg_deriveMINUS_ecdh, action_arg_encryptMINUS_aesccm, action_arg_encryptMINUS_aescbc, action_arg_encryptMINUS_aesecb, action_arg_generateMINUS_asymmetricMINUS_key, action_arg_generateMINUS_hmacMINUS_key, action_arg_generateMINUS_otpMINUS_aeadMINUS_key, action_arg_generateMINUS_wrapMINUS_key, action_arg_generateMINUS_symmetricMINUS_key, action_arg_getMINUS_deviceMINUS_info, action_arg_getMINUS_logs, action_arg_getMINUS_objectMINUS_info, action_arg_getMINUS_opaque, action_arg_getMINUS_option, action_arg_getMINUS_pseudoMINUS_random, action_arg_getMINUS_publicMINUS_key, action_arg_getMINUS_storageMINUS_info, action_arg_getMINUS_template, action_arg_getMINUS_wrapped, action_arg_getMINUS_rsaMINUS_wrapped, action_arg_getMINUS_rsaMINUS_wrappedMINUS_key, action_arg_getMINUS_deviceMINUS_pubkey, action_arg_listMINUS_objects, action_arg_putMINUS_asymmetricMINUS_key, action_arg_putMINUS_authenticationMINUS_key, action_arg_putMINUS_hmacMINUS_key, action_arg_putMINUS_opaque, action_arg_putMINUS_option, action_arg_putMINUS_otpMINUS_aeadMINUS_key, action_arg_putMINUS_symmetricMINUS_key, action_arg_putMINUS_template, action_arg_putMINUS_wrapMINUS_key, action_arg_putMINUS_rsaMINUS_wrapkey, action_arg_putMINUS_publicMINUS_wrapkey, action_arg_putMINUS_wrapped, action_arg_putMINUS_rsaMINUS_wrapped, action_arg_putMINUS_rsaMINUS_wrappedMINUS_key, action_arg_randomizeMINUS_otpMINUS_aead, action_arg_reset, action_arg_setMINUS_logMINUS_index, action_arg_signMINUS_attestationMINUS_certificate, action_arg_signMINUS_ecdsa, action_arg_signMINUS_eddsa, action_arg_signMINUS_hmac, action_arg_signMINUS_pkcs1v15, action_arg_signMINUS_pss, action_arg_signMINUS_sshMINUS_certificate }; enum enum_informat { informat__NULL = -1, informat_arg_default = 0, informat_arg_base64, informat_arg_binary, informat_arg_PEM, informat_arg_password, informat_arg_hex, informat_arg_ASCII }; enum enum_outformat { outformat__NULL = -1, outformat_arg_default = 0, outformat_arg_base64, outformat_arg_binary, outformat_arg_PEM, outformat_arg_hex, outformat_arg_ASCII }; /** @brief Where the command line options are stored */ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ enum enum_action *action_arg; /**< @brief Action to perform. */ char ** action_orig; /**< @brief Action to perform original value given at command line. */ unsigned int action_min; /**< @brief Action to perform's minimum occurreces */ unsigned int action_max; /**< @brief Action to perform's maximum occurreces */ const char *action_help; /**< @brief Action to perform help description. */ char * password_arg; /**< @brief Authentication password. */ char * password_orig; /**< @brief Authentication password original value given at command line. */ const char *password_help; /**< @brief Authentication password help description. */ int authkey_arg; /**< @brief Authentication key (default='1'). */ char * authkey_orig; /**< @brief Authentication key original value given at command line. */ const char *authkey_help; /**< @brief Authentication key help description. */ short object_id_arg; /**< @brief Object ID (default='0'). */ char * object_id_orig; /**< @brief Object ID original value given at command line. */ const char *object_id_help; /**< @brief Object ID help description. */ char * label_arg; /**< @brief Object label (default=''). */ char * label_orig; /**< @brief Object label original value given at command line. */ const char *label_help; /**< @brief Object label help description. */ char * domains_arg; /**< @brief Object domains (default='1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16'). */ char * domains_orig; /**< @brief Object domains original value given at command line. */ const char *domains_help; /**< @brief Object domains help description. */ char * capabilities_arg; /**< @brief Capabilities for an object (default='0'). */ char * capabilities_orig; /**< @brief Capabilities for an object original value given at command line. */ const char *capabilities_help; /**< @brief Capabilities for an object help description. */ char * object_type_arg; /**< @brief Object type (default='any'). */ char * object_type_orig; /**< @brief Object type original value given at command line. */ const char *object_type_help; /**< @brief Object type help description. */ char * ykhsmauth_label_arg; /**< @brief Credential label on YubiKey (implicitly enables ykhsmauth). */ char * ykhsmauth_label_orig; /**< @brief Credential label on YubiKey (implicitly enables ykhsmauth) original value given at command line. */ const char *ykhsmauth_label_help; /**< @brief Credential label on YubiKey (implicitly enables ykhsmauth) help description. */ char * ykhsmauth_reader_arg; /**< @brief Only use a matching YubiKey reader name (default=''). */ char * ykhsmauth_reader_orig; /**< @brief Only use a matching YubiKey reader name original value given at command line. */ const char *ykhsmauth_reader_help; /**< @brief Only use a matching YubiKey reader name help description. */ char * delegated_arg; /**< @brief Delegated capabilities (default='0'). */ char * delegated_orig; /**< @brief Delegated capabilities original value given at command line. */ const char *delegated_help; /**< @brief Delegated capabilities help description. */ char * new_password_arg; /**< @brief New authentication password. */ char * new_password_orig; /**< @brief New authentication password original value given at command line. */ const char *new_password_help; /**< @brief New authentication password help description. */ char * algorithm_arg; /**< @brief Operation algorithm (default='any'). */ char * algorithm_orig; /**< @brief Operation algorithm original value given at command line. */ const char *algorithm_help; /**< @brief Operation algorithm help description. */ char * oaep_arg; /**< @brief OAEP algorithm. Used primarily with asymmetric wrap (default='rsa-oaep-sha256'). */ char * oaep_orig; /**< @brief OAEP algorithm. Used primarily with asymmetric wrap original value given at command line. */ const char *oaep_help; /**< @brief OAEP algorithm. Used primarily with asymmetric wrap help description. */ char * mgf1_arg; /**< @brief MGF1 algorithm. Used primarily with asymmetric wrap (default='mgf1-sha256'). */ char * mgf1_orig; /**< @brief MGF1 algorithm. Used primarily with asymmetric wrap original value given at command line. */ const char *mgf1_help; /**< @brief MGF1 algorithm. Used primarily with asymmetric wrap help description. */ int nonce_arg; /**< @brief OTP nonce. */ char * nonce_orig; /**< @brief OTP nonce original value given at command line. */ const char *nonce_help; /**< @brief OTP nonce help description. */ char * iv_arg; /**< @brief An initialization vector as a hexadecimal string. */ char * iv_orig; /**< @brief An initialization vector as a hexadecimal string original value given at command line. */ const char *iv_help; /**< @brief An initialization vector as a hexadecimal string help description. */ int count_arg; /**< @brief Number of bytes to request (default='256'). */ char * count_orig; /**< @brief Number of bytes to request original value given at command line. */ const char *count_help; /**< @brief Number of bytes to request help description. */ int duration_arg; /**< @brief Blink duration in seconds (default='10'). */ char * duration_orig; /**< @brief Blink duration in seconds original value given at command line. */ const char *duration_help; /**< @brief Blink duration in seconds help description. */ int wrap_id_arg; /**< @brief Wrap key ID. */ char * wrap_id_orig; /**< @brief Wrap key ID original value given at command line. */ const char *wrap_id_help; /**< @brief Wrap key ID help description. */ int include_seed_flag; /**< @brief Include seed when exporting an ED25519 key under wrap (default=off). */ const char *include_seed_help; /**< @brief Include seed when exporting an ED25519 key under wrap help description. */ int template_id_arg; /**< @brief Template ID. */ char * template_id_orig; /**< @brief Template ID original value given at command line. */ const char *template_id_help; /**< @brief Template ID help description. */ int attestation_id_arg; /**< @brief Attestation ID. */ char * attestation_id_orig; /**< @brief Attestation ID original value given at command line. */ const char *attestation_id_help; /**< @brief Attestation ID help description. */ int log_index_arg; /**< @brief Log index. */ char * log_index_orig; /**< @brief Log index original value given at command line. */ const char *log_index_help; /**< @brief Log index help description. */ char * opt_name_arg; /**< @brief Device option name. */ char * opt_name_orig; /**< @brief Device option name original value given at command line. */ const char *opt_name_help; /**< @brief Device option name help description. */ char * opt_value_arg; /**< @brief Device option value. */ char * opt_value_orig; /**< @brief Device option value original value given at command line. */ const char *opt_value_help; /**< @brief Device option value help description. */ char * in_arg; /**< @brief Input data (filename) (default='-'). */ char * in_orig; /**< @brief Input data (filename) original value given at command line. */ const char *in_help; /**< @brief Input data (filename) help description. */ char * out_arg; /**< @brief Output data (filename) (default='-'). */ char * out_orig; /**< @brief Output data (filename) original value given at command line. */ const char *out_help; /**< @brief Output data (filename) help description. */ enum enum_informat informat_arg; /**< @brief Input format (default='default'). */ char * informat_orig; /**< @brief Input format original value given at command line. */ const char *informat_help; /**< @brief Input format help description. */ enum enum_outformat outformat_arg; /**< @brief Input and output format (default='default'). */ char * outformat_orig; /**< @brief Input and output format original value given at command line. */ const char *outformat_help; /**< @brief Input and output format help description. */ char * config_file_arg; /**< @brief Configuration file to read (default=''). */ char * config_file_orig; /**< @brief Configuration file to read original value given at command line. */ const char *config_file_help; /**< @brief Configuration file to read help description. */ char ** connector_arg; /**< @brief List of connectors to use. */ char ** connector_orig; /**< @brief List of connectors to use original value given at command line. */ unsigned int connector_min; /**< @brief List of connectors to use's minimum occurreces */ unsigned int connector_max; /**< @brief List of connectors to use's maximum occurreces */ const char *connector_help; /**< @brief List of connectors to use help description. */ char * cacert_arg; /**< @brief HTTPS cacert for connector. */ char * cacert_orig; /**< @brief HTTPS cacert for connector original value given at command line. */ const char *cacert_help; /**< @brief HTTPS cacert for connector help description. */ char * cert_arg; /**< @brief HTTPS client certificate to authenticate with. */ char * cert_orig; /**< @brief HTTPS client certificate to authenticate with original value given at command line. */ const char *cert_help; /**< @brief HTTPS client certificate to authenticate with help description. */ char * key_arg; /**< @brief HTTPS client certificate key. */ char * key_orig; /**< @brief HTTPS client certificate key original value given at command line. */ const char *key_help; /**< @brief HTTPS client certificate key help description. */ char * proxy_arg; /**< @brief Proxy server to use for connector. */ char * proxy_orig; /**< @brief Proxy server to use for connector original value given at command line. */ const char *proxy_help; /**< @brief Proxy server to use for connector help description. */ char * noproxy_arg; /**< @brief Comma separated list of hosts ignore proxy for. */ char * noproxy_orig; /**< @brief Comma separated list of hosts ignore proxy for original value given at command line. */ const char *noproxy_help; /**< @brief Comma separated list of hosts ignore proxy for help description. */ int verbose_arg; /**< @brief Print more information (default='0'). */ char * verbose_orig; /**< @brief Print more information original value given at command line. */ const char *verbose_help; /**< @brief Print more information help description. */ int pre_connect_flag; /**< @brief Connect immediately in interactive mode (default=off). */ const char *pre_connect_help; /**< @brief Connect immediately in interactive mode help description. */ char ** device_pubkey_arg; /**< @brief List of device public keys allowed for asymmetric authentication. */ char ** device_pubkey_orig; /**< @brief List of device public keys allowed for asymmetric authentication original value given at command line. */ unsigned int device_pubkey_min; /**< @brief List of device public keys allowed for asymmetric authentication's minimum occurreces */ unsigned int device_pubkey_max; /**< @brief List of device public keys allowed for asymmetric authentication's maximum occurreces */ const char *device_pubkey_help; /**< @brief List of device public keys allowed for asymmetric authentication help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int action_given ; /**< @brief Whether action was given. */ unsigned int password_given ; /**< @brief Whether password was given. */ unsigned int authkey_given ; /**< @brief Whether authkey was given. */ unsigned int object_id_given ; /**< @brief Whether object-id was given. */ unsigned int label_given ; /**< @brief Whether label was given. */ unsigned int domains_given ; /**< @brief Whether domains was given. */ unsigned int capabilities_given ; /**< @brief Whether capabilities was given. */ unsigned int object_type_given ; /**< @brief Whether object-type was given. */ unsigned int ykhsmauth_label_given ; /**< @brief Whether ykhsmauth-label was given. */ unsigned int ykhsmauth_reader_given ; /**< @brief Whether ykhsmauth-reader was given. */ unsigned int delegated_given ; /**< @brief Whether delegated was given. */ unsigned int new_password_given ; /**< @brief Whether new-password was given. */ unsigned int algorithm_given ; /**< @brief Whether algorithm was given. */ unsigned int oaep_given ; /**< @brief Whether oaep was given. */ unsigned int mgf1_given ; /**< @brief Whether mgf1 was given. */ unsigned int nonce_given ; /**< @brief Whether nonce was given. */ unsigned int iv_given ; /**< @brief Whether iv was given. */ unsigned int count_given ; /**< @brief Whether count was given. */ unsigned int duration_given ; /**< @brief Whether duration was given. */ unsigned int wrap_id_given ; /**< @brief Whether wrap-id was given. */ unsigned int include_seed_given ; /**< @brief Whether include-seed was given. */ unsigned int template_id_given ; /**< @brief Whether template-id was given. */ unsigned int attestation_id_given ; /**< @brief Whether attestation-id was given. */ unsigned int log_index_given ; /**< @brief Whether log-index was given. */ unsigned int opt_name_given ; /**< @brief Whether opt-name was given. */ unsigned int opt_value_given ; /**< @brief Whether opt-value was given. */ unsigned int in_given ; /**< @brief Whether in was given. */ unsigned int out_given ; /**< @brief Whether out was given. */ unsigned int informat_given ; /**< @brief Whether informat was given. */ unsigned int outformat_given ; /**< @brief Whether outformat was given. */ unsigned int config_file_given ; /**< @brief Whether config-file was given. */ unsigned int connector_given ; /**< @brief Whether connector was given. */ unsigned int cacert_given ; /**< @brief Whether cacert was given. */ unsigned int cert_given ; /**< @brief Whether cert was given. */ unsigned int key_given ; /**< @brief Whether key was given. */ unsigned int proxy_given ; /**< @brief Whether proxy was given. */ unsigned int noproxy_given ; /**< @brief Whether noproxy was given. */ unsigned int verbose_given ; /**< @brief Whether verbose was given. */ unsigned int pre_connect_given ; /**< @brief Whether pre-connect was given. */ unsigned int device_pubkey_given ; /**< @brief Whether device-pubkey was given. */ } ; /** @brief The additional parameters to pass to parser functions */ struct cmdline_parser_params { int override; /**< @brief whether to override possibly already present options (default 0) */ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ int check_required; /**< @brief whether to check that all required options were provided (default 1) */ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ } ; /** @brief the purpose string of the program */ extern const char *gengetopt_args_info_purpose; /** @brief the usage string of the program */ extern const char *gengetopt_args_info_usage; /** @brief the description string of the program */ extern const char *gengetopt_args_info_description; /** @brief all the lines making the help output */ extern const char *gengetopt_args_info_help[]; /** * The command line parser * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info); /** * The command line parser (version with additional parameters - deprecated) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_ext() instead */ int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The command line parser (version with additional parameters) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Save the contents of the option struct into an already open FILE stream. * @param outfile the stream where to dump options * @param args_info the option struct to dump * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info); /** * Save the contents of the option struct into a (text) file. * This file can be read by the config file parser (if generated by gengetopt) * @param filename the file where to save * @param args_info the option struct to save * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info); /** * Print the help */ void cmdline_parser_print_help(void); /** * Print the version */ void cmdline_parser_print_version(void); /** * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ void cmdline_parser_params_init(struct cmdline_parser_params *params); /** * Allocates dynamically a cmdline_parser_params structure and initializes * all its fields to their default values * @return the created and initialized cmdline_parser_params structure */ struct cmdline_parser_params *cmdline_parser_params_create(void); /** * Initializes the passed gengetopt_args_info structure's fields * (also set default values for options that have a default) * @param args_info the structure to initialize */ void cmdline_parser_init (struct gengetopt_args_info *args_info); /** * Deallocates the string fields of the gengetopt_args_info structure * (but does not deallocate the structure itself) * @param args_info the structure to deallocate */ void cmdline_parser_free (struct gengetopt_args_info *args_info); /** * The config file parser (deprecated version) * @param filename the name of the config file * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_config_file() instead */ int cmdline_parser_configfile (const char *filename, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The config file parser * @param filename the name of the config file * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_config_file (const char *filename, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Checks that all the required options were specified * @param args_info the structure to check * @param prog_name the name of the program that will be used to print * possible errors * @return */ int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name); extern const char *cmdline_parser_action_values[]; /**< @brief Possible values for action. */ extern const char *cmdline_parser_informat_values[]; /**< @brief Possible values for informat. */ extern const char *cmdline_parser_outformat_values[]; /**< @brief Possible values for outformat. */ #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CMDLINE_H */ yubihsm-shell-2.6.0/src/README.adoc0000644000175100001770000000642414666527773016262 0ustar runnerdocker== YubiHSM Shell YubiHSM Shell is a tool to directly interface with a YubiHSM 2 device. For the most part it is a thin wrapper around `libyubihsm` exposing most of its functions directly to the user. YubiHSM Shell can be invoked in interactive mode and from the command line. Special (national) characters are supported on MacOS and Linux platforms. On Windows, they are supported in interactive mode and the same support can be activated through the OpenSSL environment variable `OPENSSL_WIN32_UTF8` for interactive password entry in non-interactive mode (i.e if password is not given on the command line). Such characters will be encoded according to current locale settings on MacOS/Linux (typically utf-8), and always as utf-8 on Windows. === Interactive Mode To invoke YubiHSM Shell in interactive mode simply run `yubihsm-shell` with no parameters. This mode supports tab-completion (not on Windows) and "classic" terminal shortcuts (`C-p`, `C-n`, `C-a`, `C-e`, etc.) In this mode, the default Connector URL is `http://127.0.01:12345`. If a different URL is needed, it can be specified with the `--connector` option. For example, to select direct USB run [source, bash] ---- yubihsm-shell --connector yhusb:// ---- Help can be obtained by running [source, bash] ---- yubihsm> help ---- to get a list of available commands and their syntax, or by running [source, bash] ---- yubihsm> help COMMAND ---- to get help on a specific command. Debug messages can be turned on by running [source, bash] ---- yubihsm> debug all ---- other levels of verbosity are available as well. Each command has its own default input and output format. Possible choices are `PEM`, `base64`, `binary`, `hex`, `password` and `default`. Those can be changed by running [source, bash] ---- yubihsm> set informat base64 ---- or [source, bash] ---- yubihsm> set outformat hex ---- Input and Output formats are a generic modifier and some values may not make sense in some cases. The default setting can be restored by using the `default` format. === Command-line Mode It is possible to run yubihsm-shell as a non-interactive command-line utility. To do so add the `--action` option with the desired command to execute. For example, to generate an RSA 2048 key with Label `Signature_Key`, Object ID `10` and Capabilities `sign-pss`, run [source, bash] ---- $ yubihsm-shell -p password -a generate-asymmetric -A rsa2048 -i 10 -c sign-pss -l Signature_Key ---- to sign a file called `message.dat` using the previously generated key, PSS with SHA256 as padding scheme and save the result to a file called `signature.dat` run [source, bash] ---- $ yubihsm-shell -p password -a sign-pss -i 10 -A rsa-pss-sha256 --in message.dat --out signature.dat --outformat binary ---- it is then possible to extract the public key by using [source, bash] ---- yubihsm-shell -p password -a get-public-key -i 10 --out key.pem --outformat PEM ---- and verify the signature with OpenSSL by running [source, bash] ---- $ openssl dgst -sha256 -binary message.dat > digest.dat $ openssl pkeyutl -verify -in digest.dat -sigfile signature.dat -pkeyopt rsa_padding_mode:pss -pubin -inkey key.pem -pkeyopt rsa_pss_saltlen:-1 -pkeyopt digest:sha256 ---- A detailed list of possible actions and parameters is available in the manpage or by running `yubihsm-shell --help`. yubihsm-shell-2.6.0/src/version.rc.in0000644000175100001770000000215014666527773017105 0ustar runnerdocker #include #define VER_FILEVERSION @yubihsm_shell_VERSION_MAJOR@,@yubihsm_shell_VERSION_MINOR@,@yubihsm_shell_VERSION_PATCH@,0 #define VER_FILEVERSION_STR "@yubihsm_shell_VERSION_MAJOR@.@yubihsm_shell_VERSION_MINOR@.@yubihsm_shell_VERSION_PATCH@.0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_FILEVERSION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Yubico AB" VALUE "FileDescription", "YubiHSM Shell" VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "yubihsm-shell.exe" VALUE "LegalCopyright", "\xa9 Yubico AB" VALUE "OriginalFilename", "yubihsm-shell.exe" VALUE "ProductName", "YubiHSM" VALUE "ProductVersion", VER_FILEVERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END yubihsm-shell-2.6.0/src/cmdline.c0000644000175100001770000022330314666530034016231 0ustar runnerdocker/* File autogenerated by gengetopt version 2.23 generated with the following command: gengetopt --conf-parser -i /home/runner/work/yubihsm-shell/yubihsm-shell/src/cmdline.ggo --output-dir /home/runner/work/yubihsm-shell/yubihsm-shell/src cmdline The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: we make no copyright claims on it. */ /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifndef FIX_UNUSED #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ #endif #include #include "cmdline.h" const char *gengetopt_args_info_purpose = ""; const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", " -a, --action=ENUM Action to perform (possible\n values=\"benchmark\", \"blink-device\",\n \"create-otp-aead\", \"decrypt-aesccm\",\n \"decrypt-aescbc\", \"decrypt-aesecb\",\n \"decrypt-oaep\", \"decrypt-otp\",\n \"decrypt-pkcs1v15\", \"delete-object\",\n \"derive-ecdh\", \"encrypt-aesccm\",\n \"encrypt-aescbc\", \"encrypt-aesecb\",\n \"generate-asymmetric-key\",\n \"generate-hmac-key\",\n \"generate-otp-aead-key\",\n \"generate-wrap-key\",\n \"generate-symmetric-key\",\n \"get-device-info\", \"get-logs\",\n \"get-object-info\", \"get-opaque\",\n \"get-option\", \"get-pseudo-random\",\n \"get-public-key\", \"get-storage-info\",\n \"get-template\", \"get-wrapped\",\n \"get-rsa-wrapped\", \"get-rsa-wrapped-key\",\n \"get-device-pubkey\", \"list-objects\",\n \"put-asymmetric-key\",\n \"put-authentication-key\", \"put-hmac-key\",\n \"put-opaque\", \"put-option\",\n \"put-otp-aead-key\", \"put-symmetric-key\",\n \"put-template\", \"put-wrap-key\",\n \"put-rsa-wrapkey\", \"put-public-wrapkey\",\n \"put-wrapped\", \"put-rsa-wrapped\",\n \"put-rsa-wrapped-key\",\n \"randomize-otp-aead\", \"reset\",\n \"set-log-index\",\n \"sign-attestation-certificate\",\n \"sign-ecdsa\", \"sign-eddsa\",\n \"sign-hmac\", \"sign-pkcs1v15\",\n \"sign-pss\", \"sign-ssh-certificate\")", " -p, --password=STRING Authentication password", " --authkey=INT Authentication key (default=`1')", " -i, --object-id=SHORT Object ID (default=`0')", " -l, --label=STRING Object label (default=`')", " -d, --domains=STRING Object domains\n (default=`1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16')", " -c, --capabilities=STRING Capabilities for an object (default=`0')", " -t, --object-type=STRING Object type (default=`any')", " -y, --ykhsmauth-label=STRING Credential label on YubiKey (implicitly enables\n ykhsmauth)", " -r, --ykhsmauth-reader=STRING Only use a matching YubiKey reader name\n (default=`')", " --delegated=STRING Delegated capabilities (default=`0')", " --new-password=STRING New authentication password", " -A, --algorithm=STRING Operation algorithm (default=`any')", " --oaep=STRING OAEP algorithm. Used primarily with asymmetric\n wrap (default=`rsa-oaep-sha256')", " --mgf1=STRING MGF1 algorithm. Used primarily with asymmetric\n wrap (default=`mgf1-sha256')", " --nonce=INT OTP nonce", " --iv=STRING An initialization vector as a hexadecimal\n string", " --count=INT Number of bytes to request (default=`256')", " --duration=INT Blink duration in seconds (default=`10')", " --wrap-id=INT Wrap key ID", " --include-seed Include seed when exporting an ED25519 key\n under wrap (default=off)", " --template-id=INT Template ID", " --attestation-id=INT Attestation ID", " --log-index=INT Log index", " --opt-name=STRING Device option name", " --opt-value=STRING Device option value", " --in=STRING Input data (filename) (default=`-')", " --out=STRING Output data (filename) (default=`-')", " --informat=ENUM Input format (possible values=\"default\",\n \"base64\", \"binary\", \"PEM\",\n \"password\", \"hex\", \"ASCII\"\n default=`default')", " --outformat=ENUM Input and output format (possible\n values=\"default\", \"base64\", \"binary\",\n \"PEM\", \"hex\", \"ASCII\"\n default=`default')", " -f, --config-file=STRING Configuration file to read (default=`')", " -C, --connector=STRING List of connectors to use", " --cacert=STRING HTTPS cacert for connector", " --cert=STRING HTTPS client certificate to authenticate with", " --key=STRING HTTPS client certificate key", " --proxy=STRING Proxy server to use for connector", " --noproxy=STRING Comma separated list of hosts ignore proxy for", " -v, --verbose=INT Print more information (default=`0')", " -P, --pre-connect Connect immediately in interactive mode\n (default=off)", " --device-pubkey=STRING List of device public keys allowed for\n asymmetric authentication", 0 }; typedef enum {ARG_NO , ARG_FLAG , ARG_STRING , ARG_INT , ARG_SHORT , ARG_ENUM } cmdline_parser_arg_type; static void clear_given (struct gengetopt_args_info *args_info); static void clear_args (struct gengetopt_args_info *args_info); static int cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error); static int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error); struct line_list { char * string_arg; struct line_list * next; }; static struct line_list *cmd_line_list = 0; static struct line_list *cmd_line_list_tmp = 0; static void free_cmd_list(void) { /* free the list of a previous call */ if (cmd_line_list) { while (cmd_line_list) { cmd_line_list_tmp = cmd_line_list; cmd_line_list = cmd_line_list->next; free (cmd_line_list_tmp->string_arg); free (cmd_line_list_tmp); } } } const char *cmdline_parser_action_values[] = {"benchmark", "blink-device", "create-otp-aead", "decrypt-aesccm", "decrypt-aescbc", "decrypt-aesecb", "decrypt-oaep", "decrypt-otp", "decrypt-pkcs1v15", "delete-object", "derive-ecdh", "encrypt-aesccm", "encrypt-aescbc", "encrypt-aesecb", "generate-asymmetric-key", "generate-hmac-key", "generate-otp-aead-key", "generate-wrap-key", "generate-symmetric-key", "get-device-info", "get-logs", "get-object-info", "get-opaque", "get-option", "get-pseudo-random", "get-public-key", "get-storage-info", "get-template", "get-wrapped", "get-rsa-wrapped", "get-rsa-wrapped-key", "get-device-pubkey", "list-objects", "put-asymmetric-key", "put-authentication-key", "put-hmac-key", "put-opaque", "put-option", "put-otp-aead-key", "put-symmetric-key", "put-template", "put-wrap-key", "put-rsa-wrapkey", "put-public-wrapkey", "put-wrapped", "put-rsa-wrapped", "put-rsa-wrapped-key", "randomize-otp-aead", "reset", "set-log-index", "sign-attestation-certificate", "sign-ecdsa", "sign-eddsa", "sign-hmac", "sign-pkcs1v15", "sign-pss", "sign-ssh-certificate", 0}; /*< Possible values for action. */ const char *cmdline_parser_informat_values[] = {"default", "base64", "binary", "PEM", "password", "hex", "ASCII", 0}; /*< Possible values for informat. */ const char *cmdline_parser_outformat_values[] = {"default", "base64", "binary", "PEM", "hex", "ASCII", 0}; /*< Possible values for outformat. */ static char * gengetopt_strdup (const char *s); static void clear_given (struct gengetopt_args_info *args_info) { args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->action_given = 0 ; args_info->password_given = 0 ; args_info->authkey_given = 0 ; args_info->object_id_given = 0 ; args_info->label_given = 0 ; args_info->domains_given = 0 ; args_info->capabilities_given = 0 ; args_info->object_type_given = 0 ; args_info->ykhsmauth_label_given = 0 ; args_info->ykhsmauth_reader_given = 0 ; args_info->delegated_given = 0 ; args_info->new_password_given = 0 ; args_info->algorithm_given = 0 ; args_info->oaep_given = 0 ; args_info->mgf1_given = 0 ; args_info->nonce_given = 0 ; args_info->iv_given = 0 ; args_info->count_given = 0 ; args_info->duration_given = 0 ; args_info->wrap_id_given = 0 ; args_info->include_seed_given = 0 ; args_info->template_id_given = 0 ; args_info->attestation_id_given = 0 ; args_info->log_index_given = 0 ; args_info->opt_name_given = 0 ; args_info->opt_value_given = 0 ; args_info->in_given = 0 ; args_info->out_given = 0 ; args_info->informat_given = 0 ; args_info->outformat_given = 0 ; args_info->config_file_given = 0 ; args_info->connector_given = 0 ; args_info->cacert_given = 0 ; args_info->cert_given = 0 ; args_info->key_given = 0 ; args_info->proxy_given = 0 ; args_info->noproxy_given = 0 ; args_info->verbose_given = 0 ; args_info->pre_connect_given = 0 ; args_info->device_pubkey_given = 0 ; } static void clear_args (struct gengetopt_args_info *args_info) { FIX_UNUSED (args_info); args_info->action_arg = NULL; args_info->action_orig = NULL; args_info->password_arg = NULL; args_info->password_orig = NULL; args_info->authkey_arg = 1; args_info->authkey_orig = NULL; args_info->object_id_arg = 0; args_info->object_id_orig = NULL; args_info->label_arg = gengetopt_strdup (""); args_info->label_orig = NULL; args_info->domains_arg = gengetopt_strdup ("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16"); args_info->domains_orig = NULL; args_info->capabilities_arg = gengetopt_strdup ("0"); args_info->capabilities_orig = NULL; args_info->object_type_arg = gengetopt_strdup ("any"); args_info->object_type_orig = NULL; args_info->ykhsmauth_label_arg = NULL; args_info->ykhsmauth_label_orig = NULL; args_info->ykhsmauth_reader_arg = gengetopt_strdup (""); args_info->ykhsmauth_reader_orig = NULL; args_info->delegated_arg = gengetopt_strdup ("0"); args_info->delegated_orig = NULL; args_info->new_password_arg = NULL; args_info->new_password_orig = NULL; args_info->algorithm_arg = gengetopt_strdup ("any"); args_info->algorithm_orig = NULL; args_info->oaep_arg = gengetopt_strdup ("rsa-oaep-sha256"); args_info->oaep_orig = NULL; args_info->mgf1_arg = gengetopt_strdup ("mgf1-sha256"); args_info->mgf1_orig = NULL; args_info->nonce_orig = NULL; args_info->iv_arg = NULL; args_info->iv_orig = NULL; args_info->count_arg = 256; args_info->count_orig = NULL; args_info->duration_arg = 10; args_info->duration_orig = NULL; args_info->wrap_id_orig = NULL; args_info->include_seed_flag = 0; args_info->template_id_orig = NULL; args_info->attestation_id_orig = NULL; args_info->log_index_orig = NULL; args_info->opt_name_arg = NULL; args_info->opt_name_orig = NULL; args_info->opt_value_arg = NULL; args_info->opt_value_orig = NULL; args_info->in_arg = gengetopt_strdup ("-"); args_info->in_orig = NULL; args_info->out_arg = gengetopt_strdup ("-"); args_info->out_orig = NULL; args_info->informat_arg = informat_arg_default; args_info->informat_orig = NULL; args_info->outformat_arg = outformat_arg_default; args_info->outformat_orig = NULL; args_info->config_file_arg = gengetopt_strdup (""); args_info->config_file_orig = NULL; args_info->connector_arg = NULL; args_info->connector_orig = NULL; args_info->cacert_arg = NULL; args_info->cacert_orig = NULL; args_info->cert_arg = NULL; args_info->cert_orig = NULL; args_info->key_arg = NULL; args_info->key_orig = NULL; args_info->proxy_arg = NULL; args_info->proxy_orig = NULL; args_info->noproxy_arg = NULL; args_info->noproxy_orig = NULL; args_info->verbose_arg = 0; args_info->verbose_orig = NULL; args_info->pre_connect_flag = 0; args_info->device_pubkey_arg = NULL; args_info->device_pubkey_orig = NULL; } static void init_args_info(struct gengetopt_args_info *args_info) { args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->action_help = gengetopt_args_info_help[2] ; args_info->action_min = 0; args_info->action_max = 0; args_info->password_help = gengetopt_args_info_help[3] ; args_info->authkey_help = gengetopt_args_info_help[4] ; args_info->object_id_help = gengetopt_args_info_help[5] ; args_info->label_help = gengetopt_args_info_help[6] ; args_info->domains_help = gengetopt_args_info_help[7] ; args_info->capabilities_help = gengetopt_args_info_help[8] ; args_info->object_type_help = gengetopt_args_info_help[9] ; args_info->ykhsmauth_label_help = gengetopt_args_info_help[10] ; args_info->ykhsmauth_reader_help = gengetopt_args_info_help[11] ; args_info->delegated_help = gengetopt_args_info_help[12] ; args_info->new_password_help = gengetopt_args_info_help[13] ; args_info->algorithm_help = gengetopt_args_info_help[14] ; args_info->oaep_help = gengetopt_args_info_help[15] ; args_info->mgf1_help = gengetopt_args_info_help[16] ; args_info->nonce_help = gengetopt_args_info_help[17] ; args_info->iv_help = gengetopt_args_info_help[18] ; args_info->count_help = gengetopt_args_info_help[19] ; args_info->duration_help = gengetopt_args_info_help[20] ; args_info->wrap_id_help = gengetopt_args_info_help[21] ; args_info->include_seed_help = gengetopt_args_info_help[22] ; args_info->template_id_help = gengetopt_args_info_help[23] ; args_info->attestation_id_help = gengetopt_args_info_help[24] ; args_info->log_index_help = gengetopt_args_info_help[25] ; args_info->opt_name_help = gengetopt_args_info_help[26] ; args_info->opt_value_help = gengetopt_args_info_help[27] ; args_info->in_help = gengetopt_args_info_help[28] ; args_info->out_help = gengetopt_args_info_help[29] ; args_info->informat_help = gengetopt_args_info_help[30] ; args_info->outformat_help = gengetopt_args_info_help[31] ; args_info->config_file_help = gengetopt_args_info_help[32] ; args_info->connector_help = gengetopt_args_info_help[33] ; args_info->connector_min = 0; args_info->connector_max = 0; args_info->cacert_help = gengetopt_args_info_help[34] ; args_info->cert_help = gengetopt_args_info_help[35] ; args_info->key_help = gengetopt_args_info_help[36] ; args_info->proxy_help = gengetopt_args_info_help[37] ; args_info->noproxy_help = gengetopt_args_info_help[38] ; args_info->verbose_help = gengetopt_args_info_help[39] ; args_info->pre_connect_help = gengetopt_args_info_help[40] ; args_info->device_pubkey_help = gengetopt_args_info_help[41] ; args_info->device_pubkey_min = 0; args_info->device_pubkey_max = 0; } void cmdline_parser_print_version (void) { printf ("%s %s\n", (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), CMDLINE_PARSER_VERSION); if (strlen(gengetopt_args_info_versiontext) > 0) printf("\n%s\n", gengetopt_args_info_versiontext); } static void print_help_common(void) { size_t len_purpose = strlen(gengetopt_args_info_purpose); size_t len_usage = strlen(gengetopt_args_info_usage); if (len_usage > 0) { printf("%s\n", gengetopt_args_info_usage); } if (len_purpose > 0) { printf("%s\n", gengetopt_args_info_purpose); } if (len_usage || len_purpose) { printf("\n"); } if (strlen(gengetopt_args_info_description) > 0) { printf("%s\n\n", gengetopt_args_info_description); } } void cmdline_parser_print_help (void) { int i = 0; print_help_common(); while (gengetopt_args_info_help[i]) printf("%s\n", gengetopt_args_info_help[i++]); } void cmdline_parser_init (struct gengetopt_args_info *args_info) { clear_given (args_info); clear_args (args_info); init_args_info (args_info); } void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) { params->override = 0; params->initialize = 1; params->check_required = 1; params->check_ambiguity = 0; params->print_errors = 1; } } struct cmdline_parser_params * cmdline_parser_params_create(void) { struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); cmdline_parser_params_init(params); return params; } static void free_string_field (char **s) { if (*s) { free (*s); *s = 0; } } /** @brief generic value variable */ union generic_value { int int_arg; short short_arg; char *string_arg; const char *default_string_arg; }; /** @brief holds temporary values for multiple options */ struct generic_list { union generic_value arg; char *orig; struct generic_list *next; }; /** * @brief add a node at the head of the list */ static void add_node(struct generic_list **list) { struct generic_list *new_node = (struct generic_list *) malloc (sizeof (struct generic_list)); new_node->next = *list; *list = new_node; new_node->arg.string_arg = 0; new_node->orig = 0; } /** * The passed arg parameter is NOT set to 0 from this function */ static void free_multiple_field(unsigned int len, void *arg, char ***orig) { unsigned int i; if (arg) { for (i = 0; i < len; ++i) { free_string_field(&((*orig)[i])); } free (arg); free (*orig); *orig = 0; } } static void free_multiple_string_field(unsigned int len, char ***arg, char ***orig) { unsigned int i; if (*arg) { for (i = 0; i < len; ++i) { free_string_field(&((*arg)[i])); free_string_field(&((*orig)[i])); } free_string_field(&((*arg)[0])); /* free default string */ free (*arg); *arg = 0; free (*orig); *orig = 0; } } static void cmdline_parser_release (struct gengetopt_args_info *args_info) { free_multiple_field (args_info->action_given, (void *)(args_info->action_arg), &(args_info->action_orig)); args_info->action_arg = 0; free_string_field (&(args_info->password_arg)); free_string_field (&(args_info->password_orig)); free_string_field (&(args_info->authkey_orig)); free_string_field (&(args_info->object_id_orig)); free_string_field (&(args_info->label_arg)); free_string_field (&(args_info->label_orig)); free_string_field (&(args_info->domains_arg)); free_string_field (&(args_info->domains_orig)); free_string_field (&(args_info->capabilities_arg)); free_string_field (&(args_info->capabilities_orig)); free_string_field (&(args_info->object_type_arg)); free_string_field (&(args_info->object_type_orig)); free_string_field (&(args_info->ykhsmauth_label_arg)); free_string_field (&(args_info->ykhsmauth_label_orig)); free_string_field (&(args_info->ykhsmauth_reader_arg)); free_string_field (&(args_info->ykhsmauth_reader_orig)); free_string_field (&(args_info->delegated_arg)); free_string_field (&(args_info->delegated_orig)); free_string_field (&(args_info->new_password_arg)); free_string_field (&(args_info->new_password_orig)); free_string_field (&(args_info->algorithm_arg)); free_string_field (&(args_info->algorithm_orig)); free_string_field (&(args_info->oaep_arg)); free_string_field (&(args_info->oaep_orig)); free_string_field (&(args_info->mgf1_arg)); free_string_field (&(args_info->mgf1_orig)); free_string_field (&(args_info->nonce_orig)); free_string_field (&(args_info->iv_arg)); free_string_field (&(args_info->iv_orig)); free_string_field (&(args_info->count_orig)); free_string_field (&(args_info->duration_orig)); free_string_field (&(args_info->wrap_id_orig)); free_string_field (&(args_info->template_id_orig)); free_string_field (&(args_info->attestation_id_orig)); free_string_field (&(args_info->log_index_orig)); free_string_field (&(args_info->opt_name_arg)); free_string_field (&(args_info->opt_name_orig)); free_string_field (&(args_info->opt_value_arg)); free_string_field (&(args_info->opt_value_orig)); free_string_field (&(args_info->in_arg)); free_string_field (&(args_info->in_orig)); free_string_field (&(args_info->out_arg)); free_string_field (&(args_info->out_orig)); free_string_field (&(args_info->informat_orig)); free_string_field (&(args_info->outformat_orig)); free_string_field (&(args_info->config_file_arg)); free_string_field (&(args_info->config_file_orig)); free_multiple_string_field (args_info->connector_given, &(args_info->connector_arg), &(args_info->connector_orig)); free_string_field (&(args_info->cacert_arg)); free_string_field (&(args_info->cacert_orig)); free_string_field (&(args_info->cert_arg)); free_string_field (&(args_info->cert_orig)); free_string_field (&(args_info->key_arg)); free_string_field (&(args_info->key_orig)); free_string_field (&(args_info->proxy_arg)); free_string_field (&(args_info->proxy_orig)); free_string_field (&(args_info->noproxy_arg)); free_string_field (&(args_info->noproxy_orig)); free_string_field (&(args_info->verbose_orig)); free_multiple_string_field (args_info->device_pubkey_given, &(args_info->device_pubkey_arg), &(args_info->device_pubkey_orig)); clear_given (args_info); } /** * @param val the value to check * @param values the possible values * @return the index of the matched value: * -1 if no value matched, * -2 if more than one value has matched */ static int check_possible_values(const char *val, const char *values[]) { int i, found, last; size_t len; if (!val) /* otherwise strlen() crashes below */ return -1; /* -1 means no argument for the option */ found = last = 0; for (i = 0, len = strlen(val); values[i]; ++i) { if (strncmp(val, values[i], len) == 0) { ++found; last = i; if (strlen(values[i]) == len) return i; /* exact macth no need to check more */ } } if (found == 1) /* one match: OK */ return last; return (found ? -2 : -1); /* return many values or none matched */ } static void write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) { int found = -1; if (arg) { if (values) { found = check_possible_values(arg, values); } if (found >= 0) fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]); else fprintf(outfile, "%s=\"%s\"\n", opt, arg); } else { fprintf(outfile, "%s\n", opt); } } static void write_multiple_into_file(FILE *outfile, int len, const char *opt, char **arg, const char *values[]) { int i; for (i = 0; i < len; ++i) write_into_file(outfile, opt, (arg ? arg[i] : 0), values); } int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) { int i = 0; if (!outfile) { fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); return EXIT_FAILURE; } if (args_info->help_given) write_into_file(outfile, "help", 0, 0 ); if (args_info->version_given) write_into_file(outfile, "version", 0, 0 ); write_multiple_into_file(outfile, args_info->action_given, "action", args_info->action_orig, cmdline_parser_action_values); if (args_info->password_given) write_into_file(outfile, "password", args_info->password_orig, 0); if (args_info->authkey_given) write_into_file(outfile, "authkey", args_info->authkey_orig, 0); if (args_info->object_id_given) write_into_file(outfile, "object-id", args_info->object_id_orig, 0); if (args_info->label_given) write_into_file(outfile, "label", args_info->label_orig, 0); if (args_info->domains_given) write_into_file(outfile, "domains", args_info->domains_orig, 0); if (args_info->capabilities_given) write_into_file(outfile, "capabilities", args_info->capabilities_orig, 0); if (args_info->object_type_given) write_into_file(outfile, "object-type", args_info->object_type_orig, 0); if (args_info->ykhsmauth_label_given) write_into_file(outfile, "ykhsmauth-label", args_info->ykhsmauth_label_orig, 0); if (args_info->ykhsmauth_reader_given) write_into_file(outfile, "ykhsmauth-reader", args_info->ykhsmauth_reader_orig, 0); if (args_info->delegated_given) write_into_file(outfile, "delegated", args_info->delegated_orig, 0); if (args_info->new_password_given) write_into_file(outfile, "new-password", args_info->new_password_orig, 0); if (args_info->algorithm_given) write_into_file(outfile, "algorithm", args_info->algorithm_orig, 0); if (args_info->oaep_given) write_into_file(outfile, "oaep", args_info->oaep_orig, 0); if (args_info->mgf1_given) write_into_file(outfile, "mgf1", args_info->mgf1_orig, 0); if (args_info->nonce_given) write_into_file(outfile, "nonce", args_info->nonce_orig, 0); if (args_info->iv_given) write_into_file(outfile, "iv", args_info->iv_orig, 0); if (args_info->count_given) write_into_file(outfile, "count", args_info->count_orig, 0); if (args_info->duration_given) write_into_file(outfile, "duration", args_info->duration_orig, 0); if (args_info->wrap_id_given) write_into_file(outfile, "wrap-id", args_info->wrap_id_orig, 0); if (args_info->include_seed_given) write_into_file(outfile, "include-seed", 0, 0 ); if (args_info->template_id_given) write_into_file(outfile, "template-id", args_info->template_id_orig, 0); if (args_info->attestation_id_given) write_into_file(outfile, "attestation-id", args_info->attestation_id_orig, 0); if (args_info->log_index_given) write_into_file(outfile, "log-index", args_info->log_index_orig, 0); if (args_info->opt_name_given) write_into_file(outfile, "opt-name", args_info->opt_name_orig, 0); if (args_info->opt_value_given) write_into_file(outfile, "opt-value", args_info->opt_value_orig, 0); if (args_info->in_given) write_into_file(outfile, "in", args_info->in_orig, 0); if (args_info->out_given) write_into_file(outfile, "out", args_info->out_orig, 0); if (args_info->informat_given) write_into_file(outfile, "informat", args_info->informat_orig, cmdline_parser_informat_values); if (args_info->outformat_given) write_into_file(outfile, "outformat", args_info->outformat_orig, cmdline_parser_outformat_values); if (args_info->config_file_given) write_into_file(outfile, "config-file", args_info->config_file_orig, 0); write_multiple_into_file(outfile, args_info->connector_given, "connector", args_info->connector_orig, 0); if (args_info->cacert_given) write_into_file(outfile, "cacert", args_info->cacert_orig, 0); if (args_info->cert_given) write_into_file(outfile, "cert", args_info->cert_orig, 0); if (args_info->key_given) write_into_file(outfile, "key", args_info->key_orig, 0); if (args_info->proxy_given) write_into_file(outfile, "proxy", args_info->proxy_orig, 0); if (args_info->noproxy_given) write_into_file(outfile, "noproxy", args_info->noproxy_orig, 0); if (args_info->verbose_given) write_into_file(outfile, "verbose", args_info->verbose_orig, 0); if (args_info->pre_connect_given) write_into_file(outfile, "pre-connect", 0, 0 ); write_multiple_into_file(outfile, args_info->device_pubkey_given, "device-pubkey", args_info->device_pubkey_orig, 0); i = EXIT_SUCCESS; return i; } int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) { FILE *outfile; int i = 0; outfile = fopen(filename, "w"); if (!outfile) { fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } i = cmdline_parser_dump(outfile, args_info); fclose (outfile); return i; } void cmdline_parser_free (struct gengetopt_args_info *args_info) { cmdline_parser_release (args_info); } /** @brief replacement of strdup, which is not standard */ char * gengetopt_strdup (const char *s) { char *result = 0; if (!s) return result; result = (char*)malloc(strlen(s) + 1); if (result == (char*)0) return (char*)0; strcpy(result, s); return result; } static char * get_multiple_arg_token(const char *arg) { const char *tok; char *ret; size_t len, num_of_escape, i, j; if (!arg) return 0; tok = strchr (arg, ','); num_of_escape = 0; /* make sure it is not escaped */ while (tok) { if (*(tok-1) == '\\') { /* find the next one */ tok = strchr (tok+1, ','); ++num_of_escape; } else break; } if (tok) len = (size_t)(tok - arg + 1); else len = strlen (arg) + 1; len -= num_of_escape; ret = (char *) malloc (len); i = 0; j = 0; while (arg[i] && (j < len-1)) { if (arg[i] == '\\' && arg[ i + 1 ] && arg[ i + 1 ] == ',') ++i; ret[j++] = arg[i++]; } ret[len-1] = '\0'; return ret; } static const char * get_multiple_arg_token_next(const char *arg) { const char *tok; if (!arg) return 0; tok = strchr (arg, ','); /* make sure it is not escaped */ while (tok) { if (*(tok-1) == '\\') { /* find the next one */ tok = strchr (tok+1, ','); } else break; } if (! tok || strlen(tok) == 1) return 0; return tok+1; } static int check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc); int check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc) { int error_occurred = 0; if (option_given && (min > 0 || max > 0)) { if (min > 0 && max > 0) { if (min == max) { /* specific occurrences */ if (option_given != (unsigned int) min) { fprintf (stderr, "%s: %s option occurrences must be %d\n", prog_name, option_desc, min); error_occurred = 1; } } else if (option_given < (unsigned int) min || option_given > (unsigned int) max) { /* range occurrences */ fprintf (stderr, "%s: %s option occurrences must be between %d and %d\n", prog_name, option_desc, min, max); error_occurred = 1; } } else if (min > 0) { /* at least check */ if (option_given < min) { fprintf (stderr, "%s: %s option occurrences must be at least %d\n", prog_name, option_desc, min); error_occurred = 1; } } else if (max > 0) { /* at most check */ if (option_given > max) { fprintf (stderr, "%s: %s option occurrences must be at most %d\n", prog_name, option_desc, max); error_occurred = 1; } } } return error_occurred; } int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) { return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); } int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int result; result = cmdline_parser_internal (argc, argv, args_info, params, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { int result; struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) { int result = EXIT_SUCCESS; if (cmdline_parser_required2(args_info, prog_name, 0) > 0) result = EXIT_FAILURE; if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error) { int error_occurred = 0; FIX_UNUSED (additional_error); /* checks for required options */ if (check_multiple_option_occurrences(prog_name, args_info->action_given, args_info->action_min, args_info->action_max, "'--action' ('-a')")) error_occurred = 1; if (check_multiple_option_occurrences(prog_name, args_info->connector_given, args_info->connector_min, args_info->connector_max, "'--connector' ('-C')")) error_occurred = 1; if (check_multiple_option_occurrences(prog_name, args_info->device_pubkey_given, args_info->device_pubkey_min, args_info->device_pubkey_max, "'--device-pubkey'")) error_occurred = 1; /* checks for dependences among options */ return error_occurred; } static char *package_name = 0; /** * @brief updates an option * @param field the generic pointer to the field to update * @param orig_field the pointer to the orig field * @param field_given the pointer to the number of occurrence of this option * @param prev_given the pointer to the number of occurrence already seen * @param value the argument for this option (if null no arg was specified) * @param possible_values the possible values for this option (if specified) * @param default_value the default value (in case the option only accepts fixed values) * @param arg_type the type of this option * @param check_ambiguity @see cmdline_parser_params.check_ambiguity * @param override @see cmdline_parser_params.override * @param no_free whether to free a possible previous value * @param multiple_option whether this is a multiple option * @param long_opt the corresponding long option * @param short_opt the corresponding short option (or '-' if none) * @param additional_error possible further error specification */ static int update_arg(void *field, char **orig_field, unsigned int *field_given, unsigned int *prev_given, char *value, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, int check_ambiguity, int override, int no_free, int multiple_option, const char *long_opt, char short_opt, const char *additional_error) { char *stop_char = 0; const char *val = value; int found; char **string_field; FIX_UNUSED (field); stop_char = 0; found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0) { if (short_opt != '-') fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n", package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (field_given && *field_given && ! override) return 0; if (prev_given) (*prev_given)++; if (field_given) (*field_given)++; if (possible_values) val = possible_values[found]; switch(arg_type) { case ARG_FLAG: *((int *)field) = !*((int *)field); break; case ARG_INT: if (val) *((int *)field) = strtol (val, &stop_char, 0); break; case ARG_SHORT: if (val) *((short *)field) = (short)strtol (val, &stop_char, 0); break; case ARG_ENUM: if (val) *((int *)field) = found; break; case ARG_STRING: if (val) { string_field = (char **)field; if (!no_free && *string_field) free (*string_field); /* free previous string */ *string_field = gengetopt_strdup (val); } break; default: break; }; /* check numeric conversion */ switch(arg_type) { case ARG_INT: case ARG_SHORT: if (val && !(stop_char && *stop_char == '\0')) { fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val); return 1; /* failure */ } break; default: ; }; /* store the original value */ switch(arg_type) { case ARG_NO: case ARG_FLAG: break; default: if (value && orig_field) { if (no_free) { *orig_field = value; } else { if (*orig_field) free (*orig_field); /* free previous string */ *orig_field = gengetopt_strdup (value); } } }; return 0; /* OK */ } /** * @brief store information about a multiple option in a temporary list * @param list where to (temporarily) store multiple options */ static int update_multiple_arg_temp(struct generic_list **list, unsigned int *prev_given, const char *val, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, const char *long_opt, char short_opt, const char *additional_error) { /* store single arguments */ char *multi_token; const char *multi_next; if (arg_type == ARG_NO) { (*prev_given)++; return 0; /* OK */ } multi_token = get_multiple_arg_token(val); multi_next = get_multiple_arg_token_next (val); while (1) { add_node (list); if (update_arg((void *)&((*list)->arg), &((*list)->orig), 0, prev_given, multi_token, possible_values, default_value, arg_type, 0, 1, 1, 1, long_opt, short_opt, additional_error)) { if (multi_token) free(multi_token); return 1; /* failure */ } if (multi_next) { multi_token = get_multiple_arg_token(multi_next); multi_next = get_multiple_arg_token_next (multi_next); } else break; } return 0; /* OK */ } /** * @brief free the passed list (including possible string argument) */ static void free_list(struct generic_list *list, short string_arg) { if (list) { struct generic_list *tmp; while (list) { tmp = list; if (string_arg && list->arg.string_arg) free (list->arg.string_arg); if (list->orig) free (list->orig); list = list->next; free (tmp); } } } /** * @brief updates a multiple option starting from the passed list */ static void update_multiple_arg(void *field, char ***orig_field, unsigned int field_given, unsigned int prev_given, union generic_value *default_value, cmdline_parser_arg_type arg_type, struct generic_list *list) { int i; struct generic_list *tmp; if (prev_given && list) { *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *)); switch(arg_type) { case ARG_INT: case ARG_ENUM: *((int **)field) = (int *)realloc (*((int **)field), (field_given + prev_given) * sizeof (int)); break; case ARG_SHORT: *((short **)field) = (short *)realloc (*((short **)field), (field_given + prev_given) * sizeof (short)); break; case ARG_STRING: *((char ***)field) = (char **)realloc (*((char ***)field), (field_given + prev_given) * sizeof (char *)); break; default: break; }; for (i = (prev_given - 1); i >= 0; --i) { tmp = list; switch(arg_type) { case ARG_INT: (*((int **)field))[i + field_given] = tmp->arg.int_arg; break; case ARG_SHORT: (*((short **)field))[i + field_given] = tmp->arg.short_arg; break; case ARG_ENUM: (*((int **)field))[i + field_given] = tmp->arg.int_arg; break; case ARG_STRING: (*((char ***)field))[i + field_given] = tmp->arg.string_arg; break; default: break; } (*orig_field) [i + field_given] = list->orig; list = list->next; free (tmp); } } else { /* set the default value */ if (default_value && ! field_given) { switch(arg_type) { case ARG_INT: case ARG_ENUM: if (! *((int **)field)) { *((int **)field) = (int *)malloc (sizeof (int)); (*((int **)field))[0] = default_value->int_arg; } break; case ARG_SHORT: if (! *((short **)field)) { *((short **)field) = (short *)malloc (sizeof (short)); (*((short **)field))[0] = default_value->short_arg; } break; case ARG_STRING: if (! *((char ***)field)) { *((char ***)field) = (char **)malloc (sizeof (char *)); (*((char ***)field))[0] = gengetopt_strdup(default_value->string_arg); } break; default: break; } if (!(*orig_field)) { *orig_field = (char **) malloc (sizeof (char *)); (*orig_field)[0] = 0; } } } } int cmdline_parser_internal ( int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { int c; /* Character of the parsed option. */ struct generic_list * action_list = NULL; struct generic_list * connector_list = NULL; struct generic_list * device_pubkey_list = NULL; int error_occurred = 0; struct gengetopt_args_info local_args_info; int override; int initialize; int check_required; int check_ambiguity; package_name = argv[0]; /* TODO: Why is this here? It is not used anywhere. */ override = params->override; FIX_UNUSED(override); initialize = params->initialize; check_required = params->check_required; /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); cmdline_parser_init (&local_args_info); optarg = 0; optind = 0; opterr = params->print_errors; optopt = '?'; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "action", 1, NULL, 'a' }, { "password", 1, NULL, 'p' }, { "authkey", 1, NULL, 0 }, { "object-id", 1, NULL, 'i' }, { "label", 1, NULL, 'l' }, { "domains", 1, NULL, 'd' }, { "capabilities", 1, NULL, 'c' }, { "object-type", 1, NULL, 't' }, { "ykhsmauth-label", 1, NULL, 'y' }, { "ykhsmauth-reader", 1, NULL, 'r' }, { "delegated", 1, NULL, 0 }, { "new-password", 1, NULL, 0 }, { "algorithm", 1, NULL, 'A' }, { "oaep", 1, NULL, 0 }, { "mgf1", 1, NULL, 0 }, { "nonce", 1, NULL, 0 }, { "iv", 1, NULL, 0 }, { "count", 1, NULL, 0 }, { "duration", 1, NULL, 0 }, { "wrap-id", 1, NULL, 0 }, { "include-seed", 0, NULL, 0 }, { "template-id", 1, NULL, 0 }, { "attestation-id", 1, NULL, 0 }, { "log-index", 1, NULL, 0 }, { "opt-name", 1, NULL, 0 }, { "opt-value", 1, NULL, 0 }, { "in", 1, NULL, 0 }, { "out", 1, NULL, 0 }, { "informat", 1, NULL, 0 }, { "outformat", 1, NULL, 0 }, { "config-file", 1, NULL, 'f' }, { "connector", 1, NULL, 'C' }, { "cacert", 1, NULL, 0 }, { "cert", 1, NULL, 0 }, { "key", 1, NULL, 0 }, { "proxy", 1, NULL, 0 }, { "noproxy", 1, NULL, 0 }, { "verbose", 1, NULL, 'v' }, { "pre-connect", 0, NULL, 'P' }, { "device-pubkey", 1, NULL, 0 }, { 0, 0, 0, 0 } }; c = getopt_long (argc, argv, "hVa:p:i:l:d:c:t:y:r:A:f:C:v:P", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'a': /* Action to perform. */ if (update_multiple_arg_temp(&action_list, &(local_args_info.action_given), optarg, cmdline_parser_action_values, 0, ARG_ENUM, "action", 'a', additional_error)) goto failure; break; case 'p': /* Authentication password. */ if (update_arg( (void *)&(args_info->password_arg), &(args_info->password_orig), &(args_info->password_given), &(local_args_info.password_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "password", 'p', additional_error)) goto failure; break; case 'i': /* Object ID. */ if (update_arg( (void *)&(args_info->object_id_arg), &(args_info->object_id_orig), &(args_info->object_id_given), &(local_args_info.object_id_given), optarg, 0, "0", ARG_SHORT, check_ambiguity, override, 0, 0, "object-id", 'i', additional_error)) goto failure; break; case 'l': /* Object label. */ if (update_arg( (void *)&(args_info->label_arg), &(args_info->label_orig), &(args_info->label_given), &(local_args_info.label_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "label", 'l', additional_error)) goto failure; break; case 'd': /* Object domains. */ if (update_arg( (void *)&(args_info->domains_arg), &(args_info->domains_orig), &(args_info->domains_given), &(local_args_info.domains_given), optarg, 0, "1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16", ARG_STRING, check_ambiguity, override, 0, 0, "domains", 'd', additional_error)) goto failure; break; case 'c': /* Capabilities for an object. */ if (update_arg( (void *)&(args_info->capabilities_arg), &(args_info->capabilities_orig), &(args_info->capabilities_given), &(local_args_info.capabilities_given), optarg, 0, "0", ARG_STRING, check_ambiguity, override, 0, 0, "capabilities", 'c', additional_error)) goto failure; break; case 't': /* Object type. */ if (update_arg( (void *)&(args_info->object_type_arg), &(args_info->object_type_orig), &(args_info->object_type_given), &(local_args_info.object_type_given), optarg, 0, "any", ARG_STRING, check_ambiguity, override, 0, 0, "object-type", 't', additional_error)) goto failure; break; case 'y': /* Credential label on YubiKey (implicitly enables ykhsmauth). */ if (update_arg( (void *)&(args_info->ykhsmauth_label_arg), &(args_info->ykhsmauth_label_orig), &(args_info->ykhsmauth_label_given), &(local_args_info.ykhsmauth_label_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "ykhsmauth-label", 'y', additional_error)) goto failure; break; case 'r': /* Only use a matching YubiKey reader name. */ if (update_arg( (void *)&(args_info->ykhsmauth_reader_arg), &(args_info->ykhsmauth_reader_orig), &(args_info->ykhsmauth_reader_given), &(local_args_info.ykhsmauth_reader_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "ykhsmauth-reader", 'r', additional_error)) goto failure; break; case 'A': /* Operation algorithm. */ if (update_arg( (void *)&(args_info->algorithm_arg), &(args_info->algorithm_orig), &(args_info->algorithm_given), &(local_args_info.algorithm_given), optarg, 0, "any", ARG_STRING, check_ambiguity, override, 0, 0, "algorithm", 'A', additional_error)) goto failure; break; case 'f': /* Configuration file to read. */ if (update_arg( (void *)&(args_info->config_file_arg), &(args_info->config_file_orig), &(args_info->config_file_given), &(local_args_info.config_file_given), optarg, 0, "", ARG_STRING, check_ambiguity, override, 0, 0, "config-file", 'f', additional_error)) goto failure; break; case 'C': /* List of connectors to use. */ if (update_multiple_arg_temp(&connector_list, &(local_args_info.connector_given), optarg, 0, 0, ARG_STRING, "connector", 'C', additional_error)) goto failure; break; case 'v': /* Print more information. */ if (update_arg( (void *)&(args_info->verbose_arg), &(args_info->verbose_orig), &(args_info->verbose_given), &(local_args_info.verbose_given), optarg, 0, "0", ARG_INT, check_ambiguity, override, 0, 0, "verbose", 'v', additional_error)) goto failure; break; case 'P': /* Connect immediately in interactive mode. */ if (update_arg((void *)&(args_info->pre_connect_flag), 0, &(args_info->pre_connect_given), &(local_args_info.pre_connect_given), optarg, 0, 0, ARG_FLAG, check_ambiguity, override, 1, 0, "pre-connect", 'P', additional_error)) goto failure; break; case 0: /* Long option with no short option */ /* Authentication key. */ if (strcmp (long_options[option_index].name, "authkey") == 0) { if (update_arg( (void *)&(args_info->authkey_arg), &(args_info->authkey_orig), &(args_info->authkey_given), &(local_args_info.authkey_given), optarg, 0, "1", ARG_INT, check_ambiguity, override, 0, 0, "authkey", '-', additional_error)) goto failure; } /* Delegated capabilities. */ else if (strcmp (long_options[option_index].name, "delegated") == 0) { if (update_arg( (void *)&(args_info->delegated_arg), &(args_info->delegated_orig), &(args_info->delegated_given), &(local_args_info.delegated_given), optarg, 0, "0", ARG_STRING, check_ambiguity, override, 0, 0, "delegated", '-', additional_error)) goto failure; } /* New authentication password. */ else if (strcmp (long_options[option_index].name, "new-password") == 0) { if (update_arg( (void *)&(args_info->new_password_arg), &(args_info->new_password_orig), &(args_info->new_password_given), &(local_args_info.new_password_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "new-password", '-', additional_error)) goto failure; } /* OAEP algorithm. Used primarily with asymmetric wrap. */ else if (strcmp (long_options[option_index].name, "oaep") == 0) { if (update_arg( (void *)&(args_info->oaep_arg), &(args_info->oaep_orig), &(args_info->oaep_given), &(local_args_info.oaep_given), optarg, 0, "rsa-oaep-sha256", ARG_STRING, check_ambiguity, override, 0, 0, "oaep", '-', additional_error)) goto failure; } /* MGF1 algorithm. Used primarily with asymmetric wrap. */ else if (strcmp (long_options[option_index].name, "mgf1") == 0) { if (update_arg( (void *)&(args_info->mgf1_arg), &(args_info->mgf1_orig), &(args_info->mgf1_given), &(local_args_info.mgf1_given), optarg, 0, "mgf1-sha256", ARG_STRING, check_ambiguity, override, 0, 0, "mgf1", '-', additional_error)) goto failure; } /* OTP nonce. */ else if (strcmp (long_options[option_index].name, "nonce") == 0) { if (update_arg( (void *)&(args_info->nonce_arg), &(args_info->nonce_orig), &(args_info->nonce_given), &(local_args_info.nonce_given), optarg, 0, 0, ARG_INT, check_ambiguity, override, 0, 0, "nonce", '-', additional_error)) goto failure; } /* An initialization vector as a hexadecimal string. */ else if (strcmp (long_options[option_index].name, "iv") == 0) { if (update_arg( (void *)&(args_info->iv_arg), &(args_info->iv_orig), &(args_info->iv_given), &(local_args_info.iv_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "iv", '-', additional_error)) goto failure; } /* Number of bytes to request. */ else if (strcmp (long_options[option_index].name, "count") == 0) { if (update_arg( (void *)&(args_info->count_arg), &(args_info->count_orig), &(args_info->count_given), &(local_args_info.count_given), optarg, 0, "256", ARG_INT, check_ambiguity, override, 0, 0, "count", '-', additional_error)) goto failure; } /* Blink duration in seconds. */ else if (strcmp (long_options[option_index].name, "duration") == 0) { if (update_arg( (void *)&(args_info->duration_arg), &(args_info->duration_orig), &(args_info->duration_given), &(local_args_info.duration_given), optarg, 0, "10", ARG_INT, check_ambiguity, override, 0, 0, "duration", '-', additional_error)) goto failure; } /* Wrap key ID. */ else if (strcmp (long_options[option_index].name, "wrap-id") == 0) { if (update_arg( (void *)&(args_info->wrap_id_arg), &(args_info->wrap_id_orig), &(args_info->wrap_id_given), &(local_args_info.wrap_id_given), optarg, 0, 0, ARG_INT, check_ambiguity, override, 0, 0, "wrap-id", '-', additional_error)) goto failure; } /* Include seed when exporting an ED25519 key under wrap. */ else if (strcmp (long_options[option_index].name, "include-seed") == 0) { if (update_arg((void *)&(args_info->include_seed_flag), 0, &(args_info->include_seed_given), &(local_args_info.include_seed_given), optarg, 0, 0, ARG_FLAG, check_ambiguity, override, 1, 0, "include-seed", '-', additional_error)) goto failure; } /* Template ID. */ else if (strcmp (long_options[option_index].name, "template-id") == 0) { if (update_arg( (void *)&(args_info->template_id_arg), &(args_info->template_id_orig), &(args_info->template_id_given), &(local_args_info.template_id_given), optarg, 0, 0, ARG_INT, check_ambiguity, override, 0, 0, "template-id", '-', additional_error)) goto failure; } /* Attestation ID. */ else if (strcmp (long_options[option_index].name, "attestation-id") == 0) { if (update_arg( (void *)&(args_info->attestation_id_arg), &(args_info->attestation_id_orig), &(args_info->attestation_id_given), &(local_args_info.attestation_id_given), optarg, 0, 0, ARG_INT, check_ambiguity, override, 0, 0, "attestation-id", '-', additional_error)) goto failure; } /* Log index. */ else if (strcmp (long_options[option_index].name, "log-index") == 0) { if (update_arg( (void *)&(args_info->log_index_arg), &(args_info->log_index_orig), &(args_info->log_index_given), &(local_args_info.log_index_given), optarg, 0, 0, ARG_INT, check_ambiguity, override, 0, 0, "log-index", '-', additional_error)) goto failure; } /* Device option name. */ else if (strcmp (long_options[option_index].name, "opt-name") == 0) { if (update_arg( (void *)&(args_info->opt_name_arg), &(args_info->opt_name_orig), &(args_info->opt_name_given), &(local_args_info.opt_name_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "opt-name", '-', additional_error)) goto failure; } /* Device option value. */ else if (strcmp (long_options[option_index].name, "opt-value") == 0) { if (update_arg( (void *)&(args_info->opt_value_arg), &(args_info->opt_value_orig), &(args_info->opt_value_given), &(local_args_info.opt_value_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "opt-value", '-', additional_error)) goto failure; } /* Input data (filename). */ else if (strcmp (long_options[option_index].name, "in") == 0) { if (update_arg( (void *)&(args_info->in_arg), &(args_info->in_orig), &(args_info->in_given), &(local_args_info.in_given), optarg, 0, "-", ARG_STRING, check_ambiguity, override, 0, 0, "in", '-', additional_error)) goto failure; } /* Output data (filename). */ else if (strcmp (long_options[option_index].name, "out") == 0) { if (update_arg( (void *)&(args_info->out_arg), &(args_info->out_orig), &(args_info->out_given), &(local_args_info.out_given), optarg, 0, "-", ARG_STRING, check_ambiguity, override, 0, 0, "out", '-', additional_error)) goto failure; } /* Input format. */ else if (strcmp (long_options[option_index].name, "informat") == 0) { if (update_arg( (void *)&(args_info->informat_arg), &(args_info->informat_orig), &(args_info->informat_given), &(local_args_info.informat_given), optarg, cmdline_parser_informat_values, "default", ARG_ENUM, check_ambiguity, override, 0, 0, "informat", '-', additional_error)) goto failure; } /* Input and output format. */ else if (strcmp (long_options[option_index].name, "outformat") == 0) { if (update_arg( (void *)&(args_info->outformat_arg), &(args_info->outformat_orig), &(args_info->outformat_given), &(local_args_info.outformat_given), optarg, cmdline_parser_outformat_values, "default", ARG_ENUM, check_ambiguity, override, 0, 0, "outformat", '-', additional_error)) goto failure; } /* HTTPS cacert for connector. */ else if (strcmp (long_options[option_index].name, "cacert") == 0) { if (update_arg( (void *)&(args_info->cacert_arg), &(args_info->cacert_orig), &(args_info->cacert_given), &(local_args_info.cacert_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "cacert", '-', additional_error)) goto failure; } /* HTTPS client certificate to authenticate with. */ else if (strcmp (long_options[option_index].name, "cert") == 0) { if (update_arg( (void *)&(args_info->cert_arg), &(args_info->cert_orig), &(args_info->cert_given), &(local_args_info.cert_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "cert", '-', additional_error)) goto failure; } /* HTTPS client certificate key. */ else if (strcmp (long_options[option_index].name, "key") == 0) { if (update_arg( (void *)&(args_info->key_arg), &(args_info->key_orig), &(args_info->key_given), &(local_args_info.key_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "key", '-', additional_error)) goto failure; } /* Proxy server to use for connector. */ else if (strcmp (long_options[option_index].name, "proxy") == 0) { if (update_arg( (void *)&(args_info->proxy_arg), &(args_info->proxy_orig), &(args_info->proxy_given), &(local_args_info.proxy_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "proxy", '-', additional_error)) goto failure; } /* Comma separated list of hosts ignore proxy for. */ else if (strcmp (long_options[option_index].name, "noproxy") == 0) { if (update_arg( (void *)&(args_info->noproxy_arg), &(args_info->noproxy_orig), &(args_info->noproxy_given), &(local_args_info.noproxy_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "noproxy", '-', additional_error)) goto failure; } /* List of device public keys allowed for asymmetric authentication. */ else if (strcmp (long_options[option_index].name, "device-pubkey") == 0) { if (update_multiple_arg_temp(&device_pubkey_list, &(local_args_info.device_pubkey_given), optarg, 0, 0, ARG_STRING, "device-pubkey", '-', additional_error)) goto failure; } break; case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ } /* while */ update_multiple_arg((void *)&(args_info->action_arg), &(args_info->action_orig), args_info->action_given, local_args_info.action_given, 0, ARG_ENUM, action_list); update_multiple_arg((void *)&(args_info->connector_arg), &(args_info->connector_orig), args_info->connector_given, local_args_info.connector_given, 0, ARG_STRING, connector_list); update_multiple_arg((void *)&(args_info->device_pubkey_arg), &(args_info->device_pubkey_orig), args_info->device_pubkey_given, local_args_info.device_pubkey_given, 0, ARG_STRING, device_pubkey_list); args_info->action_given += local_args_info.action_given; local_args_info.action_given = 0; args_info->connector_given += local_args_info.connector_given; local_args_info.connector_given = 0; args_info->device_pubkey_given += local_args_info.device_pubkey_given; local_args_info.device_pubkey_given = 0; if (check_required) { error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error); } cmdline_parser_release (&local_args_info); if ( error_occurred ) return (EXIT_FAILURE); return 0; failure: free_list (action_list, 0 ); free_list (connector_list, 1 ); free_list (device_pubkey_list, 1 ); cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } #ifndef CONFIG_FILE_LINE_SIZE #define CONFIG_FILE_LINE_SIZE 2048 #endif #define ADDITIONAL_ERROR " in configuration file " #define CONFIG_FILE_LINE_BUFFER_SIZE (CONFIG_FILE_LINE_SIZE+3) /* 3 is for "--" and "=" */ static int _cmdline_parser_configfile (const char *filename, int *my_argc) { FILE* file; char my_argv[CONFIG_FILE_LINE_BUFFER_SIZE+1]; char linebuf[CONFIG_FILE_LINE_SIZE]; int line_num = 0; int result = 0, equal; char *fopt, *farg; char *str_index; size_t len, next_token; char delimiter; if ((file = fopen(filename, "r")) == 0) { fprintf (stderr, "%s: Error opening configuration file '%s'\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } while ((fgets(linebuf, CONFIG_FILE_LINE_SIZE, file)) != 0) { ++line_num; my_argv[0] = '\0'; len = strlen(linebuf); if (len > (CONFIG_FILE_LINE_BUFFER_SIZE-1)) { fprintf (stderr, "%s:%s:%d: Line too long in configuration file\n", CMDLINE_PARSER_PACKAGE, filename, line_num); result = EXIT_FAILURE; break; } /* find first non-whitespace character in the line */ next_token = strspn (linebuf, " \t\r\n"); str_index = linebuf + next_token; if ( str_index[0] == '\0' || str_index[0] == '#') continue; /* empty line or comment line is skipped */ fopt = str_index; /* truncate fopt at the end of the first non-valid character */ next_token = strcspn (fopt, " \t\r\n="); if (fopt[next_token] == '\0') /* the line is over */ { farg = 0; equal = 0; goto noarg; } /* remember if equal sign is present */ equal = (fopt[next_token] == '='); fopt[next_token++] = '\0'; /* advance pointers to the next token after the end of fopt */ next_token += strspn (fopt + next_token, " \t\r\n"); /* check for the presence of equal sign, and if so, skip it */ if ( !equal ) if ((equal = (fopt[next_token] == '='))) { next_token++; next_token += strspn (fopt + next_token, " \t\r\n"); } str_index += next_token; /* find argument */ farg = str_index; if ( farg[0] == '\"' || farg[0] == '\'' ) { /* quoted argument */ str_index = strchr (++farg, str_index[0] ); /* skip opening quote */ if (! str_index) { fprintf (stderr, "%s:%s:%d: unterminated string in configuration file\n", CMDLINE_PARSER_PACKAGE, filename, line_num); result = EXIT_FAILURE; break; } } else { /* read up the remaining part up to a delimiter */ next_token = strcspn (farg, " \t\r\n#\'\""); str_index += next_token; } /* truncate farg at the delimiter and store it for further check */ delimiter = *str_index, *str_index++ = '\0'; /* everything but comment is illegal at the end of line */ if (delimiter != '\0' && delimiter != '#') { str_index += strspn(str_index, " \t\r\n"); if (*str_index != '\0' && *str_index != '#') { fprintf (stderr, "%s:%s:%d: malformed string in configuration file\n", CMDLINE_PARSER_PACKAGE, filename, line_num); result = EXIT_FAILURE; break; } } noarg: if (!strcmp(fopt,"include")) { if (farg && *farg) { result = _cmdline_parser_configfile(farg, my_argc); } else { fprintf(stderr, "%s:%s:%d: include requires a filename argument.\n", CMDLINE_PARSER_PACKAGE, filename, line_num); } continue; } len = strlen(fopt); strcat (my_argv, len > 1 ? "--" : "-"); strcat (my_argv, fopt); if (len > 1 && ((farg && *farg) || equal)) strcat (my_argv, "="); if (farg && *farg) strcat (my_argv, farg); ++(*my_argc); cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list)); cmd_line_list_tmp->next = cmd_line_list; cmd_line_list = cmd_line_list_tmp; cmd_line_list->string_arg = gengetopt_strdup(my_argv); } /* while */ if (file) fclose(file); return result; } int cmdline_parser_configfile ( const char *filename, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; return cmdline_parser_config_file (filename, args_info, ¶ms); } int cmdline_parser_config_file (const char *filename, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int i, result; int my_argc = 1; char **my_argv_arg; char *additional_error; /* store the program name */ cmd_line_list_tmp = (struct line_list *) malloc (sizeof (struct line_list)); cmd_line_list_tmp->next = cmd_line_list; cmd_line_list = cmd_line_list_tmp; cmd_line_list->string_arg = gengetopt_strdup (CMDLINE_PARSER_PACKAGE); result = _cmdline_parser_configfile(filename, &my_argc); if (result != EXIT_FAILURE) { my_argv_arg = (char **) malloc((my_argc+1) * sizeof(char *)); cmd_line_list_tmp = cmd_line_list; for (i = my_argc - 1; i >= 0; --i) { my_argv_arg[i] = cmd_line_list_tmp->string_arg; cmd_line_list_tmp = cmd_line_list_tmp->next; } my_argv_arg[my_argc] = 0; additional_error = (char *)malloc(strlen(filename) + strlen(ADDITIONAL_ERROR) + 1); strcpy (additional_error, ADDITIONAL_ERROR); strcat (additional_error, filename); result = cmdline_parser_internal (my_argc, my_argv_arg, args_info, params, additional_error); free (additional_error); free (my_argv_arg); } free_cmd_list(); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ yubihsm-shell-2.6.0/yhwrap/0000755000175100001770000000000014666530043015172 5ustar runnerdockeryubihsm-shell-2.6.0/yhwrap/CMakeLists.txt0000644000175100001770000000476514666527773017766 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() set ( SOURCE ../common/hash.c ../common/parsing.c ../common/pkcs5.c ../common/util.c ../common/openssl-compat.c main.c ) if(WIN32) set(SOURCE ${SOURCE} cmdline.c) include(${CMAKE_SOURCE_DIR}/cmake/getopt.cmake) find_getopt() else(WIN32) include(gengetopt) add_gengetopt_files (cmdline) set(SOURCE ${SOURCE} ${GGO_C}) message("${GGO_C}") endif(WIN32) include_directories ( ${LIBCRYPTO_INCLUDEDIR} ${CMAKE_CURRENT_SOURCE_DIR}/../lib ${CMAKE_CURRENT_SOURCE_DIR}/../common ) if(${WIN32}) list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) endif(${WIN32}) # NOTE(adma): required by gengetopt add_definitions (-DPACKAGE="yubihsm-wrap") add_definitions (-DVERSION="${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") list(APPEND LCOV_REMOVE_PATTERNS "'${PROJECT_SOURCE_DIR}/yhwrap/cmdline.c'") if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") set_property(SOURCE ${GGO_C} APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-unused-but-set-variable ") endif() add_executable (yubihsm-wrap ${SOURCE}) target_link_libraries ( yubihsm-wrap ${LIBCRYPTO_LDFLAGS} ${GETOPT_LIBS} yubihsm ) set_target_properties(yubihsm-wrap PROPERTIES INSTALL_RPATH "${YUBIHSM_INSTALL_LIB_DIR}") add_coverage(yubihsm-wrap) install( TARGETS yubihsm-wrap ARCHIVE DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" LIBRARY DESTINATION "${YUBIHSM_INSTALL_LIB_DIR}" RUNTIME DESTINATION "${YUBIHSM_INSTALL_BIN_DIR}") if (NOT WITHOUT_MANPAGES) include (help2man) add_help2man_manpage (yubihsm-wrap.1 yubihsm-wrap) add_custom_target (yubihsm-wrap-man ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/yubihsm-wrap.1 ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/yubihsm-wrap.1" DESTINATION "${YUBIHSM_INSTALL_MAN_DIR}/man1") endif () yubihsm-shell-2.6.0/yhwrap/main.c0000644000175100001770000002777114666527773016320 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #include "../common/platform-config.h" #ifdef __WIN32 #include #else #include #endif #include #include #include "cmdline.h" #include "parsing.h" #include "pkcs5.h" #include "util.h" #include #define INPUT_BUFSIZE 4096 #define WRAPKEY_BUFSIZE 32 #define OBJECT_HEADER_SIZE 59 static bool wrap_data(uint8_t *key, size_t key_len, uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len) { EVP_CIPHER_CTX *ctx = NULL; const EVP_CIPHER *cipher_type; uint8_t nonce[13]; int nonce_len = 13; int tag_len = 16; int len; ctx = EVP_CIPHER_CTX_new(); if (ctx == NULL) { return false; } switch (key_len) { case 16: cipher_type = EVP_aes_128_ccm(); break; case 24: cipher_type = EVP_aes_192_ccm(); break; case 32: cipher_type = EVP_aes_256_ccm(); break; default: return false; } if (RAND_bytes(nonce, nonce_len) != 1) { return false; } memcpy(out, nonce, nonce_len); // Select cipher if (EVP_EncryptInit_ex(ctx, cipher_type, NULL, NULL, NULL) != 1) { return false; } // Set nonce length if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, nonce_len, NULL) != 1) { return false; } // Set tag length if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, tag_len, NULL) != 1) { return false; } // Initialize key and IV if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce) != 1) { return false; } // Provide the total plaintext length if (EVP_EncryptUpdate(ctx, NULL, &len, NULL, in_len) != 1) { return false; } // Provide the message to be encrypted, and obtain the encrypted output if (EVP_EncryptUpdate(ctx, out + nonce_len, &len, in, in_len) != 1) { return false; } *out_len = len; // Finalize the encryption if (EVP_EncryptFinal_ex(ctx, out + nonce_len + *out_len, &len) != 1) { return false; } *out_len += len; // Get the tag if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, tag_len, out + nonce_len + *out_len) != 1) { return false; } *out_len += tag_len; *out_len += nonce_len; // Clean up EVP_CIPHER_CTX_free(ctx); return true; } static void format_header(yh_algorithm wrapkey_algorithm, yh_capabilities capabilities, uint16_t id, uint16_t data_len, uint16_t domains, yh_object_type type, yh_algorithm algorithm, uint8_t *label, uint8_t *header) { *header = (uint8_t) wrapkey_algorithm; header++; memcpy(header, capabilities.capabilities, YH_CAPABILITIES_LEN); header += YH_CAPABILITIES_LEN; *((uint16_t *) header) = htons(id); header += sizeof(uint16_t); *((uint16_t *) header) = htons(data_len); header += sizeof(uint16_t); *((uint16_t *) header) = htons(domains); header += sizeof(uint16_t); *header = (uint8_t) type; header++; *header = (uint8_t) algorithm; header++; *header = 0x00; // Sequence header++; *header = 0x02; // Origin header++; memcpy(header, label, YH_OBJ_LABEL_LEN); header += YH_OBJ_LABEL_LEN; } static FILE *open_file(const char *name, bool input) { if (input) { if (strcmp(name, "-") == 0) { return stdin; } else { return fopen(name, "rb"); } } else { if (strcmp(name, "-") == 0) { return stdout; } else { return fopen(name, "wb"); } } } static void dump_hex(const unsigned char *buf, unsigned int len) { unsigned int i; for (i = 0; i < len; i++) { if (i && !(i % 32)) fprintf(stderr, "\n"); else if (i && !(i % 8)) fprintf(stderr, " "); fprintf(stderr, "%02x", buf[i]); } fprintf(stderr, "\n"); } int main(int argc, char *argv[]) { struct gengetopt_args_info args_info; int rc = EXIT_FAILURE; yh_rc yhrc; FILE *input_file = NULL; FILE *output_file = NULL; FILE *wrapkey_file = NULL; #pragma pack(push, 1) union { struct { uint8_t header[OBJECT_HEADER_SIZE]; uint8_t body[INPUT_BUFSIZE]; }; uint8_t buf[1]; } wrap_object = {{{0}, {0}}}; #pragma pack(pop) size_t wrap_object_len = sizeof(wrap_object.body); if (cmdline_parser(argc, argv, &args_info) != 0) { goto main_exit; } yh_algorithm algorithm; yhrc = yh_string_to_algo(args_info.algorithm_arg, &algorithm); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse algorithm: %s\n", yh_strerror(yhrc)); goto main_exit; } yh_capabilities capabilities = {{0}}; yhrc = yh_string_to_capabilities(args_info.capabilities_arg, &capabilities); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse capabilities: %s\n", yh_strerror(yhrc)); goto main_exit; } uint16_t domains; yhrc = yh_string_to_domains(args_info.domains_arg, &domains); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse domains: %s\n", yh_strerror(yhrc)); goto main_exit; } uint16_t id = args_info.id_arg; uint8_t label[YH_OBJ_LABEL_LEN] = {0}; size_t label_len = strlen(args_info.label_arg); if (label_len > YH_OBJ_LABEL_LEN) { fprintf(stderr, "Unable to parse label: label too long, maximum length is %d\n", YH_OBJ_LABEL_LEN); goto main_exit; } memcpy(label, args_info.label_arg, label_len); yh_object_type type; if (algo2type(algorithm, &type) == false) { fprintf(stderr, "Invalid algorithm\n"); goto main_exit; } yh_capabilities delegated = {{0}}; bool has_delegated = ((type == YH_AUTHENTICATION_KEY || type == YH_WRAP_KEY) ? true : false); if (has_delegated == true) { if (!args_info.delegated_given) { fprintf(stderr, "Missing delegated capabilities argument\n"); goto main_exit; } yhrc = yh_string_to_capabilities(args_info.delegated_arg, &delegated); if (yhrc != YHR_SUCCESS) { fprintf(stderr, "Unable to parse delegated capabilities: %s\n", yh_strerror(yhrc)); goto main_exit; } } input_file = open_file(args_info.in_arg, true); if (input_file == NULL) { perror("Unable to open input file"); goto main_exit; } switch (type) { case YH_AUTHENTICATION_KEY: { char password[256] = {0}; size_t password_len = sizeof(password); if (input_file == stdin) { const char *prompt = "Derivation Password: "; if (EVP_read_pw_string(password, password_len - 1, prompt, 1)) { fprintf(stderr, "Unable to read password prompt\n"); goto main_exit; } password_len = strlen(password); } else { if (read_file(input_file, (uint8_t *) password, &password_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } if (password[password_len - 1] == '\n') { password_len--; } if (password[password_len - 1] == '\r') { password_len--; } password[password_len] = '\0'; } uint8_t key[YH_KEY_LEN * 2]; bool ret = pkcs5_pbkdf2_hmac((const uint8_t *) password, password_len, (const uint8_t *) YH_DEFAULT_SALT, strlen(YH_DEFAULT_SALT), YH_DEFAULT_ITERS, _SHA256, key, sizeof(key)); if (ret == false) { fprintf(stderr, "Unable to derive keys\n"); goto main_exit; } memcpy(wrap_object.body, delegated.capabilities, YH_CAPABILITIES_LEN); wrap_object_len -= YH_CAPABILITIES_LEN; memcpy(wrap_object.body + YH_CAPABILITIES_LEN, key, YH_KEY_LEN); memcpy(wrap_object.body + YH_CAPABILITIES_LEN + YH_KEY_LEN, key + YH_KEY_LEN, YH_KEY_LEN); wrap_object_len = YH_CAPABILITIES_LEN + YH_KEY_LEN * 2; } break; case YH_WRAP_KEY: { memcpy(wrap_object.body, delegated.capabilities, YH_CAPABILITIES_LEN); wrap_object_len -= YH_CAPABILITIES_LEN; if (read_file(input_file, wrap_object.body + YH_CAPABILITIES_LEN, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } wrap_object_len += YH_CAPABILITIES_LEN; } break; case YH_ASYMMETRIC_KEY: { yh_algorithm parsed_algorithm; if (read_file(input_file, wrap_object.body, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } if (read_private_key(wrap_object.body, wrap_object_len, &parsed_algorithm, wrap_object.body, &wrap_object_len, true) != true) { fprintf(stderr, "Unable to read asymmetric private key\n"); goto main_exit; } if (parsed_algorithm != algorithm) { fprintf(stderr, "Mismatched algorithm\n"); goto main_exit; } } break; case YH_HMAC_KEY: { if (read_file(input_file, wrap_object.body, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } if (split_hmac_key(algorithm, wrap_object.body, wrap_object_len, wrap_object.body, &wrap_object_len) != true) { fprintf(stderr, "Unable to format hmac key\n"); goto main_exit; } } break; default: if (read_file(input_file, wrap_object.body, &wrap_object_len) == false) { fprintf(stderr, "Unable to read input file\n"); goto main_exit; } } wrapkey_file = open_file(args_info.wrapkey_arg, true); if (wrapkey_file == NULL) { perror("Unable to open wrapkey file"); goto main_exit; } uint8_t wrapkey_buf[WRAPKEY_BUFSIZE]; size_t wrapkey_buf_len = sizeof(wrapkey_buf); if (read_file(wrapkey_file, wrapkey_buf, &wrapkey_buf_len) == false) { fprintf(stderr, "Unable to read wrapkey file\n"); } yh_algorithm wrapkey_algorithm; switch (wrapkey_buf_len) { case 16: wrapkey_algorithm = YH_ALGO_AES128_CCM_WRAP; break; case 24: wrapkey_algorithm = YH_ALGO_AES192_CCM_WRAP; break; case 32: wrapkey_algorithm = YH_ALGO_AES256_CCM_WRAP; break; default: fprintf(stderr, "Unable to parse wrapkey: invalid length\n"); goto main_exit; } output_file = open_file(args_info.out_arg, false); if (output_file == NULL) { perror("Unable to open output file"); goto main_exit; } format_header(wrapkey_algorithm, capabilities, id, wrap_object_len, domains, type, algorithm, label, wrap_object.header); uint8_t wrapped[2048] = {0}; size_t wrapped_len = sizeof(wrapped); if (wrap_data(wrapkey_buf, wrapkey_buf_len, wrap_object.buf, OBJECT_HEADER_SIZE + wrap_object_len, wrapped, &wrapped_len) == false) { fprintf(stderr, "Unable to wrap data\n"); goto main_exit; } if (getenv("DEBUG") != NULL) { dump_hex(wrap_object.buf, OBJECT_HEADER_SIZE + wrap_object_len); } if (write_file(wrapped, wrapped_len, output_file, _base64) == false || write_file((uint8_t *) "\n", 1, output_file, _binary) == false) { fprintf(stderr, "Unable to write output file\n"); goto main_exit; } rc = EXIT_SUCCESS; main_exit: cmdline_parser_free(&args_info); if (input_file != NULL) { fclose(input_file); input_file = NULL; } if (output_file != NULL) { fclose(output_file); output_file = NULL; } if (wrapkey_file != NULL) { fclose(wrapkey_file); wrapkey_file = NULL; } return rc; } yubihsm-shell-2.6.0/yhwrap/cmdline.ggo0000644000175100001770000000201414666527773017320 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # option "algorithm" a "Object algorithm" string option "capabilities" c "Object capabilities" string option "delegated" e "Object delegates capabilities" string optional option "domains" d "Object domains" string option "id" i "Object ID" short optional default="0" option "in" - "Input data (filename)" string option "out" - "Output data (filename)" string option "label" l "Object label" string option "wrapkey" k "Key to wrap data with (filename)" string yubihsm-shell-2.6.0/yhwrap/cmdline.h0000644000175100001770000002143014666530043016756 0ustar runnerdocker/** @file cmdline.h * @brief The header file for the command line option parser * generated by GNU Gengetopt version 2.23 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten * @author GNU Gengetopt */ #ifndef CMDLINE_H #define CMDLINE_H /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* for FILE */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CMDLINE_PARSER_PACKAGE /** @brief the program name (used for printing errors) */ #define CMDLINE_PARSER_PACKAGE PACKAGE #endif #ifndef CMDLINE_PARSER_PACKAGE_NAME /** @brief the complete program name (used for help and version) */ #ifdef PACKAGE_NAME #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE_NAME #else #define CMDLINE_PARSER_PACKAGE_NAME PACKAGE #endif #endif #ifndef CMDLINE_PARSER_VERSION /** @brief the program version */ #define CMDLINE_PARSER_VERSION VERSION #endif /** @brief Where the command line options are stored */ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ char * algorithm_arg; /**< @brief Object algorithm. */ char * algorithm_orig; /**< @brief Object algorithm original value given at command line. */ const char *algorithm_help; /**< @brief Object algorithm help description. */ char * capabilities_arg; /**< @brief Object capabilities. */ char * capabilities_orig; /**< @brief Object capabilities original value given at command line. */ const char *capabilities_help; /**< @brief Object capabilities help description. */ char * delegated_arg; /**< @brief Object delegates capabilities. */ char * delegated_orig; /**< @brief Object delegates capabilities original value given at command line. */ const char *delegated_help; /**< @brief Object delegates capabilities help description. */ char * domains_arg; /**< @brief Object domains. */ char * domains_orig; /**< @brief Object domains original value given at command line. */ const char *domains_help; /**< @brief Object domains help description. */ short id_arg; /**< @brief Object ID (default='0'). */ char * id_orig; /**< @brief Object ID original value given at command line. */ const char *id_help; /**< @brief Object ID help description. */ char * in_arg; /**< @brief Input data (filename). */ char * in_orig; /**< @brief Input data (filename) original value given at command line. */ const char *in_help; /**< @brief Input data (filename) help description. */ char * out_arg; /**< @brief Output data (filename). */ char * out_orig; /**< @brief Output data (filename) original value given at command line. */ const char *out_help; /**< @brief Output data (filename) help description. */ char * label_arg; /**< @brief Object label. */ char * label_orig; /**< @brief Object label original value given at command line. */ const char *label_help; /**< @brief Object label help description. */ char * wrapkey_arg; /**< @brief Key to wrap data with (filename). */ char * wrapkey_orig; /**< @brief Key to wrap data with (filename) original value given at command line. */ const char *wrapkey_help; /**< @brief Key to wrap data with (filename) help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int algorithm_given ; /**< @brief Whether algorithm was given. */ unsigned int capabilities_given ; /**< @brief Whether capabilities was given. */ unsigned int delegated_given ; /**< @brief Whether delegated was given. */ unsigned int domains_given ; /**< @brief Whether domains was given. */ unsigned int id_given ; /**< @brief Whether id was given. */ unsigned int in_given ; /**< @brief Whether in was given. */ unsigned int out_given ; /**< @brief Whether out was given. */ unsigned int label_given ; /**< @brief Whether label was given. */ unsigned int wrapkey_given ; /**< @brief Whether wrapkey was given. */ } ; /** @brief The additional parameters to pass to parser functions */ struct cmdline_parser_params { int override; /**< @brief whether to override possibly already present options (default 0) */ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ int check_required; /**< @brief whether to check that all required options were provided (default 1) */ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ } ; /** @brief the purpose string of the program */ extern const char *gengetopt_args_info_purpose; /** @brief the usage string of the program */ extern const char *gengetopt_args_info_usage; /** @brief the description string of the program */ extern const char *gengetopt_args_info_description; /** @brief all the lines making the help output */ extern const char *gengetopt_args_info_help[]; /** * The command line parser * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info); /** * The command line parser (version with additional parameters - deprecated) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_ext() instead */ int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The command line parser (version with additional parameters) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Save the contents of the option struct into an already open FILE stream. * @param outfile the stream where to dump options * @param args_info the option struct to dump * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info); /** * Save the contents of the option struct into a (text) file. * This file can be read by the config file parser (if generated by gengetopt) * @param filename the file where to save * @param args_info the option struct to save * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info); /** * Print the help */ void cmdline_parser_print_help(void); /** * Print the version */ void cmdline_parser_print_version(void); /** * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ void cmdline_parser_params_init(struct cmdline_parser_params *params); /** * Allocates dynamically a cmdline_parser_params structure and initializes * all its fields to their default values * @return the created and initialized cmdline_parser_params structure */ struct cmdline_parser_params *cmdline_parser_params_create(void); /** * Initializes the passed gengetopt_args_info structure's fields * (also set default values for options that have a default) * @param args_info the structure to initialize */ void cmdline_parser_init (struct gengetopt_args_info *args_info); /** * Deallocates the string fields of the gengetopt_args_info structure * (but does not deallocate the structure itself) * @param args_info the structure to deallocate */ void cmdline_parser_free (struct gengetopt_args_info *args_info); /** * Checks that all the required options were specified * @param args_info the structure to check * @param prog_name the name of the program that will be used to print * possible errors * @return */ int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CMDLINE_H */ yubihsm-shell-2.6.0/yhwrap/README.adoc0000644000175100001770000000472414666527773017006 0ustar runnerdocker== YubiHSM Wrap YubiHSM Wrap is a command-line tool to create "offline wraps" for a YubiHSM 2 device. One of the functionalities supported by the YubiHSM is to import objects under wrap. The typical use is to generate an object on one device, export it under wrap using a Wrap Key and import it to a different device which has the same Wrap Key. At times it is also useful to be able to create those wrapped objects from a computer, so that they can be encrypted at rest and also easily sent to devices for use. === Example This example shows how to generate a private key using OpenSSL, wrap it to a pre-shared Wrap Key and import it on a device. The first thing we need is a Wrap Key that we will use to wrap the object. For this example we are going to use `00112233445566778899aabbccddeeff` We first save it to a file called `wrap.key` by running [source, bash] ---- $ echo -en '\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff' >wrap.key ---- The Wrap Key has to also exist on the YubiHSM. We can import it in the device and give it Object ID `20` by running [source, bash] ---- $ yubihsm-shell -p password -a put-wrap-key -i 20 -c all --delegated all --informat bin --in wrap.key ---- At this point we can use OpenSSL to generate the RSA key that we would like to wrap and import [source, bash] ---- $ openssl genrsa -out private.pem ---- We can now use `yubihsm-wrap` to produce the wrapped version of the private key. Specifically, we will be asking for the key to have, once imported, Object ID `30`, label `RSA_Key` and belong to Domains `1`, `2` and `5`. [source, bash] ---- $ yubihsm-wrap -a rsa2048 -c sign-pkcs -d 1,2,5 --id 30 --label RSA_Key --in private.pem --wrapkey wrap.key --out private.yhw ---- The output file `private.yhw` is the wrapped version of the key and it is ready to be imported in the device using the Wrap Key that we stored before. The command to do that is [source, bash] ---- $ yubihsm-shell -p password -a put-wrapped --wrap-id 20 --in private.yhw ---- We should now be able to retrieve information about the Asymmetric Key with Object ID `30` by running [source, bash] ---- $ yubihsm-shell -p password -a get-object-info -i 30 -t asymmetric-key Using default connector URL: http://localhost:12345 Session keepalive set up to run every 15 seconds Created session 0 id: 0x001e, type: asymmetric-key, algorithm: rsa2048, label: "RSA_Key", length: 896, domains: 1:2:5, sequence: 0, origin: imported:imported_wrapped, capabilities: sign-pkcs ---- yubihsm-shell-2.6.0/yhwrap/version.rc.in0000644000175100001770000000214514666527773017634 0ustar runnerdocker #include #define VER_FILEVERSION @yubihsm_shell_VERSION_MAJOR@,@yubihsm_shell_VERSION_MINOR@,@yubihsm_shell_VERSION_PATCH@,0 #define VER_FILEVERSION_STR "@yubihsm_shell_VERSION_MAJOR@.@yubihsm_shell_VERSION_MINOR@.@yubihsm_shell_VERSION_PATCH@.0" VS_VERSION_INFO VERSIONINFO FILEVERSION VER_FILEVERSION PRODUCTVERSION VER_FILEVERSION FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif FILEOS 0x40004L FILETYPE 0x2L FILESUBTYPE 0x0L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "CompanyName", "Yubico AB" VALUE "FileDescription", "YubiHSM Wrap" VALUE "FileVersion", VER_FILEVERSION_STR VALUE "InternalName", "yubihsm-wrap.exe" VALUE "LegalCopyright", "\xa9 Yubico AB" VALUE "OriginalFilename", "yubihsm-wrap.exe" VALUE "ProductName", "YubiHSM" VALUE "ProductVersion", VER_FILEVERSION_STR END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END yubihsm-shell-2.6.0/yhwrap/cmdline.c0000644000175100001770000005351314666530043016760 0ustar runnerdocker/* File autogenerated by gengetopt version 2.23 generated with the following command: gengetopt -i /home/runner/work/yubihsm-shell/yubihsm-shell/yhwrap/cmdline.ggo --output-dir /home/runner/work/yubihsm-shell/yubihsm-shell/yhwrap cmdline The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: we make no copyright claims on it. */ /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifndef FIX_UNUSED #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */ #endif #include #include "cmdline.h" const char *gengetopt_args_info_purpose = ""; const char *gengetopt_args_info_usage = "Usage: " CMDLINE_PARSER_PACKAGE " [OPTION]..."; const char *gengetopt_args_info_versiontext = ""; const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", " -a, --algorithm=STRING Object algorithm", " -c, --capabilities=STRING Object capabilities", " -e, --delegated=STRING Object delegates capabilities", " -d, --domains=STRING Object domains", " -i, --id=SHORT Object ID (default=`0')", " --in=STRING Input data (filename)", " --out=STRING Output data (filename)", " -l, --label=STRING Object label", " -k, --wrapkey=STRING Key to wrap data with (filename)", 0 }; typedef enum {ARG_NO , ARG_STRING , ARG_SHORT } cmdline_parser_arg_type; static void clear_given (struct gengetopt_args_info *args_info); static void clear_args (struct gengetopt_args_info *args_info); static int cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error); static int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error); static char * gengetopt_strdup (const char *s); static void clear_given (struct gengetopt_args_info *args_info) { args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->algorithm_given = 0 ; args_info->capabilities_given = 0 ; args_info->delegated_given = 0 ; args_info->domains_given = 0 ; args_info->id_given = 0 ; args_info->in_given = 0 ; args_info->out_given = 0 ; args_info->label_given = 0 ; args_info->wrapkey_given = 0 ; } static void clear_args (struct gengetopt_args_info *args_info) { FIX_UNUSED (args_info); args_info->algorithm_arg = NULL; args_info->algorithm_orig = NULL; args_info->capabilities_arg = NULL; args_info->capabilities_orig = NULL; args_info->delegated_arg = NULL; args_info->delegated_orig = NULL; args_info->domains_arg = NULL; args_info->domains_orig = NULL; args_info->id_arg = 0; args_info->id_orig = NULL; args_info->in_arg = NULL; args_info->in_orig = NULL; args_info->out_arg = NULL; args_info->out_orig = NULL; args_info->label_arg = NULL; args_info->label_orig = NULL; args_info->wrapkey_arg = NULL; args_info->wrapkey_orig = NULL; } static void init_args_info(struct gengetopt_args_info *args_info) { args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->algorithm_help = gengetopt_args_info_help[2] ; args_info->capabilities_help = gengetopt_args_info_help[3] ; args_info->delegated_help = gengetopt_args_info_help[4] ; args_info->domains_help = gengetopt_args_info_help[5] ; args_info->id_help = gengetopt_args_info_help[6] ; args_info->in_help = gengetopt_args_info_help[7] ; args_info->out_help = gengetopt_args_info_help[8] ; args_info->label_help = gengetopt_args_info_help[9] ; args_info->wrapkey_help = gengetopt_args_info_help[10] ; } void cmdline_parser_print_version (void) { printf ("%s %s\n", (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE), CMDLINE_PARSER_VERSION); if (strlen(gengetopt_args_info_versiontext) > 0) printf("\n%s\n", gengetopt_args_info_versiontext); } static void print_help_common(void) { size_t len_purpose = strlen(gengetopt_args_info_purpose); size_t len_usage = strlen(gengetopt_args_info_usage); if (len_usage > 0) { printf("%s\n", gengetopt_args_info_usage); } if (len_purpose > 0) { printf("%s\n", gengetopt_args_info_purpose); } if (len_usage || len_purpose) { printf("\n"); } if (strlen(gengetopt_args_info_description) > 0) { printf("%s\n\n", gengetopt_args_info_description); } } void cmdline_parser_print_help (void) { int i = 0; print_help_common(); while (gengetopt_args_info_help[i]) printf("%s\n", gengetopt_args_info_help[i++]); } void cmdline_parser_init (struct gengetopt_args_info *args_info) { clear_given (args_info); clear_args (args_info); init_args_info (args_info); } void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) { params->override = 0; params->initialize = 1; params->check_required = 1; params->check_ambiguity = 0; params->print_errors = 1; } } struct cmdline_parser_params * cmdline_parser_params_create(void) { struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); cmdline_parser_params_init(params); return params; } static void free_string_field (char **s) { if (*s) { free (*s); *s = 0; } } static void cmdline_parser_release (struct gengetopt_args_info *args_info) { free_string_field (&(args_info->algorithm_arg)); free_string_field (&(args_info->algorithm_orig)); free_string_field (&(args_info->capabilities_arg)); free_string_field (&(args_info->capabilities_orig)); free_string_field (&(args_info->delegated_arg)); free_string_field (&(args_info->delegated_orig)); free_string_field (&(args_info->domains_arg)); free_string_field (&(args_info->domains_orig)); free_string_field (&(args_info->id_orig)); free_string_field (&(args_info->in_arg)); free_string_field (&(args_info->in_orig)); free_string_field (&(args_info->out_arg)); free_string_field (&(args_info->out_orig)); free_string_field (&(args_info->label_arg)); free_string_field (&(args_info->label_orig)); free_string_field (&(args_info->wrapkey_arg)); free_string_field (&(args_info->wrapkey_orig)); clear_given (args_info); } static void write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[]) { FIX_UNUSED (values); if (arg) { fprintf(outfile, "%s=\"%s\"\n", opt, arg); } else { fprintf(outfile, "%s\n", opt); } } int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) { int i = 0; if (!outfile) { fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); return EXIT_FAILURE; } if (args_info->help_given) write_into_file(outfile, "help", 0, 0 ); if (args_info->version_given) write_into_file(outfile, "version", 0, 0 ); if (args_info->algorithm_given) write_into_file(outfile, "algorithm", args_info->algorithm_orig, 0); if (args_info->capabilities_given) write_into_file(outfile, "capabilities", args_info->capabilities_orig, 0); if (args_info->delegated_given) write_into_file(outfile, "delegated", args_info->delegated_orig, 0); if (args_info->domains_given) write_into_file(outfile, "domains", args_info->domains_orig, 0); if (args_info->id_given) write_into_file(outfile, "id", args_info->id_orig, 0); if (args_info->in_given) write_into_file(outfile, "in", args_info->in_orig, 0); if (args_info->out_given) write_into_file(outfile, "out", args_info->out_orig, 0); if (args_info->label_given) write_into_file(outfile, "label", args_info->label_orig, 0); if (args_info->wrapkey_given) write_into_file(outfile, "wrapkey", args_info->wrapkey_orig, 0); i = EXIT_SUCCESS; return i; } int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) { FILE *outfile; int i = 0; outfile = fopen(filename, "w"); if (!outfile) { fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } i = cmdline_parser_dump(outfile, args_info); fclose (outfile); return i; } void cmdline_parser_free (struct gengetopt_args_info *args_info) { cmdline_parser_release (args_info); } /** @brief replacement of strdup, which is not standard */ char * gengetopt_strdup (const char *s) { char *result = 0; if (!s) return result; result = (char*)malloc(strlen(s) + 1); if (result == (char*)0) return (char*)0; strcpy(result, s); return result; } int cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info) { return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); } int cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int result; result = cmdline_parser_internal (argc, argv, args_info, params, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { int result; struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; result = cmdline_parser_internal (argc, argv, args_info, ¶ms, 0); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) { int result = EXIT_SUCCESS; if (cmdline_parser_required2(args_info, prog_name, 0) > 0) result = EXIT_FAILURE; if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error) { int error_occurred = 0; FIX_UNUSED (additional_error); /* checks for required options */ if (! args_info->algorithm_given) { fprintf (stderr, "%s: '--algorithm' ('-a') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->capabilities_given) { fprintf (stderr, "%s: '--capabilities' ('-c') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->domains_given) { fprintf (stderr, "%s: '--domains' ('-d') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->in_given) { fprintf (stderr, "%s: '--in' option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->out_given) { fprintf (stderr, "%s: '--out' option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->label_given) { fprintf (stderr, "%s: '--label' ('-l') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } if (! args_info->wrapkey_given) { fprintf (stderr, "%s: '--wrapkey' ('-k') option required%s\n", prog_name, (additional_error ? additional_error : "")); error_occurred = 1; } /* checks for dependences among options */ return error_occurred; } static char *package_name = 0; /** * @brief updates an option * @param field the generic pointer to the field to update * @param orig_field the pointer to the orig field * @param field_given the pointer to the number of occurrence of this option * @param prev_given the pointer to the number of occurrence already seen * @param value the argument for this option (if null no arg was specified) * @param possible_values the possible values for this option (if specified) * @param default_value the default value (in case the option only accepts fixed values) * @param arg_type the type of this option * @param check_ambiguity @see cmdline_parser_params.check_ambiguity * @param override @see cmdline_parser_params.override * @param no_free whether to free a possible previous value * @param multiple_option whether this is a multiple option * @param long_opt the corresponding long option * @param short_opt the corresponding short option (or '-' if none) * @param additional_error possible further error specification */ static int update_arg(void *field, char **orig_field, unsigned int *field_given, unsigned int *prev_given, char *value, const char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, int check_ambiguity, int override, int no_free, int multiple_option, const char *long_opt, char short_opt, const char *additional_error) { char *stop_char = 0; const char *val = value; int found; char **string_field; FIX_UNUSED (field); stop_char = 0; found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } FIX_UNUSED (default_value); if (field_given && *field_given && ! override) return 0; if (prev_given) (*prev_given)++; if (field_given) (*field_given)++; if (possible_values) val = possible_values[found]; switch(arg_type) { case ARG_SHORT: if (val) *((short *)field) = (short)strtol (val, &stop_char, 0); break; case ARG_STRING: if (val) { string_field = (char **)field; if (!no_free && *string_field) free (*string_field); /* free previous string */ *string_field = gengetopt_strdup (val); } break; default: break; }; /* check numeric conversion */ switch(arg_type) { case ARG_SHORT: if (val && !(stop_char && *stop_char == '\0')) { fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val); return 1; /* failure */ } break; default: ; }; /* store the original value */ switch(arg_type) { case ARG_NO: break; default: if (value && orig_field) { if (no_free) { *orig_field = value; } else { if (*orig_field) free (*orig_field); /* free previous string */ *orig_field = gengetopt_strdup (value); } } }; return 0; /* OK */ } int cmdline_parser_internal ( int argc, char **argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { int c; /* Character of the parsed option. */ int error_occurred = 0; struct gengetopt_args_info local_args_info; int override; int initialize; int check_required; int check_ambiguity; package_name = argv[0]; /* TODO: Why is this here? It is not used anywhere. */ override = params->override; FIX_UNUSED(override); initialize = params->initialize; check_required = params->check_required; /* TODO: Why is this here? It is not used anywhere. */ check_ambiguity = params->check_ambiguity; FIX_UNUSED(check_ambiguity); if (initialize) cmdline_parser_init (args_info); cmdline_parser_init (&local_args_info); optarg = 0; optind = 0; opterr = params->print_errors; optopt = '?'; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "algorithm", 1, NULL, 'a' }, { "capabilities", 1, NULL, 'c' }, { "delegated", 1, NULL, 'e' }, { "domains", 1, NULL, 'd' }, { "id", 1, NULL, 'i' }, { "in", 1, NULL, 0 }, { "out", 1, NULL, 0 }, { "label", 1, NULL, 'l' }, { "wrapkey", 1, NULL, 'k' }, { 0, 0, 0, 0 } }; c = getopt_long (argc, argv, "hVa:c:e:d:i:l:k:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'a': /* Object algorithm. */ if (update_arg( (void *)&(args_info->algorithm_arg), &(args_info->algorithm_orig), &(args_info->algorithm_given), &(local_args_info.algorithm_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "algorithm", 'a', additional_error)) goto failure; break; case 'c': /* Object capabilities. */ if (update_arg( (void *)&(args_info->capabilities_arg), &(args_info->capabilities_orig), &(args_info->capabilities_given), &(local_args_info.capabilities_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "capabilities", 'c', additional_error)) goto failure; break; case 'e': /* Object delegates capabilities. */ if (update_arg( (void *)&(args_info->delegated_arg), &(args_info->delegated_orig), &(args_info->delegated_given), &(local_args_info.delegated_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "delegated", 'e', additional_error)) goto failure; break; case 'd': /* Object domains. */ if (update_arg( (void *)&(args_info->domains_arg), &(args_info->domains_orig), &(args_info->domains_given), &(local_args_info.domains_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "domains", 'd', additional_error)) goto failure; break; case 'i': /* Object ID. */ if (update_arg( (void *)&(args_info->id_arg), &(args_info->id_orig), &(args_info->id_given), &(local_args_info.id_given), optarg, 0, "0", ARG_SHORT, check_ambiguity, override, 0, 0, "id", 'i', additional_error)) goto failure; break; case 'l': /* Object label. */ if (update_arg( (void *)&(args_info->label_arg), &(args_info->label_orig), &(args_info->label_given), &(local_args_info.label_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "label", 'l', additional_error)) goto failure; break; case 'k': /* Key to wrap data with (filename). */ if (update_arg( (void *)&(args_info->wrapkey_arg), &(args_info->wrapkey_orig), &(args_info->wrapkey_given), &(local_args_info.wrapkey_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "wrapkey", 'k', additional_error)) goto failure; break; case 0: /* Long option with no short option */ /* Input data (filename). */ if (strcmp (long_options[option_index].name, "in") == 0) { if (update_arg( (void *)&(args_info->in_arg), &(args_info->in_orig), &(args_info->in_given), &(local_args_info.in_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "in", '-', additional_error)) goto failure; } /* Output data (filename). */ else if (strcmp (long_options[option_index].name, "out") == 0) { if (update_arg( (void *)&(args_info->out_arg), &(args_info->out_orig), &(args_info->out_given), &(local_args_info.out_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "out", '-', additional_error)) goto failure; } break; case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ } /* while */ if (check_required) { error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error); } cmdline_parser_release (&local_args_info); if ( error_occurred ) return (EXIT_FAILURE); return 0; failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */ yubihsm-shell-2.6.0/common/0000755000175100001770000000000014666530015015147 5ustar runnerdockeryubihsm-shell-2.6.0/common/parsing.c0000644000175100001770000000515314666527773017003 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include "parsing.h" #define READ_STR_PROMPT_BASE "Enter %s: " bool read_string(const char *name, char *str_buf, size_t str_buf_len, enum input_visibility visibility) { char prompt[sizeof(READ_STR_PROMPT_BASE) + 64] = {0}; int ret; if (str_buf_len < 1) { fprintf(stderr, "Unable to read %s: buffer too small\n", name); return false; } ret = snprintf(prompt, sizeof(prompt), READ_STR_PROMPT_BASE, name); if (ret < 0 || ((unsigned int) ret) > (sizeof(prompt) - 1)) { fprintf(stderr, "Unable to read %s: snprintf failed\n", name); return false; } bool checked = false; switch (visibility) { case VISIBLE: fprintf(stdout, "%s", prompt); str_buf = fgets(str_buf, str_buf_len, stdin); if (str_buf == NULL) { return false; } str_buf[strlen(str_buf) - 1] = '\0'; break; case HIDDEN_CHECKED: checked = true; case HIDDEN_UNCHECKED: ret = EVP_read_pw_string(str_buf, str_buf_len - 1, prompt, checked); if (ret != 0) { fprintf(stderr, "Retrieving %s failed (%d)\n", name, ret); return false; } break; } return true; } bool hex_decode(const char *in, uint8_t *out, size_t *len) { int pos = 0; if (in == NULL || out == NULL || len == NULL) { return false; } size_t in_len = strlen(in); if (in_len > 0 && in[in_len - 1] == '\n') { in_len--; } if (in_len > 0 && in[in_len - 1] == '\r') { in_len--; } if (in_len % 2 != 0) { return false; } else if (in_len / 2 > *len) { return false; } for (size_t i = 0; i < in_len / 2; i++) { char *endptr = NULL; char buf[3] = {0}; long num; errno = 0; buf[0] = in[pos]; buf[1] = in[pos + 1]; num = strtol(buf, &endptr, 16); if (errno != 0 || num < 0 || num > UCHAR_MAX || *endptr != '\0') { return false; } out[i] = (uint8_t) num; pos += 2; } *len = in_len / 2; return true; } yubihsm-shell-2.6.0/common/platform-config.h.in0000644000175100001770000000315614666527773021042 0ustar runnerdocker/* * 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: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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 * OWNER 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 YUBIHSM_CONFIG_H #define YUBIHSM_CONFIG_H #ifdef __cplusplus extern "C" { #endif #cmakedefine _WIN32_BCRYPT @WIN32_BCRYPT@ #cmakedefine __WIN32 @__WIN32@ #cmakedefine _WIN32 @_WIN32@ #cmakedefine _MSVC @_MSVC@ #ifdef __cplusplus } #endif #endif yubihsm-shell-2.6.0/common/rand.h0000644000175100001770000000210614666527773016264 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* rand.h ** ** Implements platform specific random generation operations */ #ifndef _YUBICOM_RAND_H_ #define _YUBICOM_RAND_H_ #include #include #include #include "../common/platform-config.h" #ifdef __cplusplus extern "C" { #endif #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif bool YH_INTERNAL rand_generate(uint8_t *buf, size_t cb_buf); #ifdef __cplusplus } #endif #endif /* _YUBICOM_RAND_H_ */ yubihsm-shell-2.6.0/common/hash.h0000644000175100001770000000335314666527773016270 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* hash.h ** ** Implements platform specific hashing operations */ #ifndef _YUBICOM_HASH_H_ #define _YUBICOM_HASH_H_ #include #include #include #include "../common/platform-config.h" #ifdef __cplusplus extern "C" { #endif typedef enum { _NONE, _SHA1, _SHA256, _SHA384, _SHA512, } hash_t; #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif bool YH_INTERNAL hash_bytes(const uint8_t *in, size_t len, hash_t hash, uint8_t *out, size_t *out_len); typedef struct _hash_ctx _hash_ctx, *hash_ctx; bool YH_INTERNAL hash_create(hash_ctx *ctx, hash_t hash); bool YH_INTERNAL hash_init(hash_ctx ctx); bool YH_INTERNAL hash_update(hash_ctx ctx, const uint8_t *in, size_t cb_in); bool YH_INTERNAL hash_final(hash_ctx ctx, uint8_t *out, size_t *pcb_out); bool YH_INTERNAL hash_destroy(hash_ctx ctx); #ifndef _WIN32_BCRYPT #include const YH_INTERNAL EVP_MD *get_hash(hash_t hash); #else #include #include LPCWSTR YH_INTERNAL get_hash(hash_t hash); #endif #ifdef __cplusplus } #endif #endif /* _YUBICOM_HASH_H_ */ yubihsm-shell-2.6.0/common/util.c0000644000175100001770000004674114666527773016325 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include "openssl-compat.h" #include "util.h" #include "insecure_memzero.h" #include "hash.h" bool set_component(unsigned char *in_ptr, const BIGNUM *bn, int element_len) { return BN_bn2binpad(bn, in_ptr, element_len) == element_len; } static unsigned const char sha1oid[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x04, 0x14}; static unsigned const char sha256oid[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20}; static unsigned const char sha384oid[] = {0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30}; static unsigned const char sha512oid[] = {0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40}; static unsigned const char PEM_private_header[] = "-----BEGIN PRIVATE KEY-----\n"; static unsigned const char PEM_private_trailer[] = "-----END PRIVATE KEY-----\n"; static unsigned const char PEM_public_header[] = "-----BEGIN PUBLIC KEY-----\n"; static unsigned const char PEM_public_trailer[] = "-----END PUBLIC KEY-----\n"; static unsigned const char ed25519private_oid[] = {0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04, 0x20}; static unsigned const char ed25519public_oid[] = {0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00}; bool read_ed25519_key(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len) { uint8_t decoded[128]; size_t decoded_len = sizeof(decoded); if (in_len < (28 + 26)) { return false; } if (memcmp(in, PEM_private_header, 28) != 0 || memcmp(in + in_len - 26, PEM_private_trailer, 25) != 0) { return false; } int ret; BIO *b64 = NULL; BIO *bio = NULL; b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { return false; } bio = BIO_new(BIO_s_mem()); if (bio == NULL) { BIO_free_all(b64); return false; } BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); BIO_push(b64, bio); (void) BIO_write(bio, in + 28, in_len - 28 - 25); (void) BIO_flush(bio); ret = BIO_read(b64, decoded, decoded_len); BIO_free_all(b64); if (ret <= 0 || ret != 48) { return false; } if (memcmp(decoded, ed25519private_oid, sizeof(ed25519private_oid)) != 0) { return false; } memcpy(out, decoded + 16, 32); *out_len = 32; insecure_memzero(decoded, 48); return true; } bool read_private_key(uint8_t *buf, size_t len, yh_algorithm *algo, uint8_t *bytes, size_t *bytes_len, bool internal_repr) { size_t out_len = *bytes_len; if (read_ed25519_key(buf, len, bytes, &out_len) == true) { *algo = YH_ALGO_EC_ED25519; if (internal_repr == true) { #if (OPENSSL_VERSION_NUMBER < 0x10101000L) || defined(LIBRESSL_VERSION_NUMBER) return false; #else EVP_PKEY *pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_ED25519, NULL, bytes, out_len); if (pkey == NULL) { return false; } size_t public_key_len = 0xff; if (EVP_PKEY_get_raw_public_key(pkey, bytes + 64, &public_key_len) != 1 || public_key_len != 32) { EVP_PKEY_free(pkey); return false; } EVP_PKEY_free(pkey); if (hash_bytes(bytes, out_len, _SHA512, bytes, bytes_len) == false) { return false; } bytes[0] &= 248; bytes[31] &= 127; bytes[31] |= 64; for (uint8_t i = 0; i < 16; i++) { uint8_t tmp = bytes[i]; bytes[i] = bytes[31 - i]; bytes[31 - i] = tmp; } *bytes_len += public_key_len; #endif } return true; } EVP_PKEY *private_key; BIO *bio = BIO_new(BIO_s_mem()); if (bio == NULL) { return false; } (void) BIO_write(bio, buf, len); private_key = PEM_read_bio_PrivateKey(bio, NULL, NULL, /*password*/ NULL); BIO_free_all(bio); if (private_key == NULL) { return false; } bool ret = false; RSA *rsa = NULL; BIGNUM *x = NULL; BIGNUM *y = NULL; EC_KEY *ec_private = NULL; switch (EVP_PKEY_base_id(private_key)) { case EVP_PKEY_RSA: { rsa = EVP_PKEY_get1_RSA(private_key); if (rsa == NULL) { goto cleanup; } unsigned char e[4]; int size = RSA_size(rsa); const BIGNUM *bn_n, *bn_e, *bn_p, *bn_q; RSA_get0_key(rsa, &bn_n, &bn_e, NULL); RSA_get0_factors(rsa, &bn_p, &bn_q); if (set_component(e, bn_e, 3) == false || !(e[0] == 0x01 && e[1] == 0x00 && e[2] == 0x01)) { goto cleanup; } if (size == 256) { *algo = YH_ALGO_RSA_2048; } else if (size == 384) { *algo = YH_ALGO_RSA_3072; } else if (size == 512) { *algo = YH_ALGO_RSA_4096; } else { goto cleanup; } if (set_component(bytes, bn_p, size / 2) == false) { goto cleanup; } if (set_component(bytes + size / 2, bn_q, size / 2) == false) { goto cleanup; } if (internal_repr == true) { const BIGNUM *dmp1, *dmq1, *iqmp; uint8_t *ptr = bytes + size; RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); if (set_component(ptr, dmp1, size / 2) == false) { goto cleanup; } ptr += size / 2; if (set_component(ptr, dmq1, size / 2) == false) { goto cleanup; } ptr += size / 2; if (set_component(ptr, iqmp, size / 2) == false) { goto cleanup; } ptr += size / 2; if (set_component(ptr, bn_n, size) == false) { goto cleanup; } *bytes_len = (size / 2) * 7; } else { *bytes_len = size; } } break; case EVP_PKEY_EC: { ec_private = EVP_PKEY_get1_EC_KEY(private_key); if (ec_private == NULL) { goto cleanup; } const BIGNUM *s = EC_KEY_get0_private_key(ec_private); const EC_GROUP *group = EC_KEY_get0_group(ec_private); int curve = EC_GROUP_get_curve_name(group); int size = 0; if (curve == NID_X9_62_prime256v1) { *algo = YH_ALGO_EC_P256; size = 32; } else if (curve == NID_secp384r1) { *algo = YH_ALGO_EC_P384; size = 48; } else if (curve == NID_secp521r1) { *algo = YH_ALGO_EC_P521; size = 66; } else if (curve == NID_secp224r1) { *algo = YH_ALGO_EC_P224; size = 28; #ifdef NID_brainpoolP256r1 } else if (curve == NID_brainpoolP256r1) { *algo = YH_ALGO_EC_BP256; size = 32; #endif #ifdef NID_brainpoolP384r1 } else if (curve == NID_brainpoolP384r1) { *algo = YH_ALGO_EC_BP384; size = 48; #endif #ifdef NID_brainpoolP512r1 } else if (curve == NID_brainpoolP512r1) { *algo = YH_ALGO_EC_BP512; size = 64; #endif } else if (curve == NID_secp256k1) { *algo = YH_ALGO_EC_K256; size = 32; } else { goto cleanup; } if (set_component(bytes, s, size) == false) { goto cleanup; } if (internal_repr == true) { const EC_POINT *ec_public = EC_KEY_get0_public_key(ec_private); x = BN_new(); if (x == NULL) { goto cleanup; } y = BN_new(); if (y == NULL) { goto cleanup; } if (EC_POINT_get_affine_coordinates_GFp(group, ec_public, x, y, NULL) == 0) { goto cleanup; } uint8_t *ptr = bytes + size; if (set_component(ptr, x, size) == false) { goto cleanup; } ptr += size; if (set_component(ptr, y, size) == false) { goto cleanup; } *bytes_len = size * 3; } else { *bytes_len = size; } } break; default: goto cleanup; } ret = true; cleanup: if (rsa != NULL) { RSA_free(rsa); rsa = NULL; } if (x != NULL) { BN_free(x); x = NULL; } if (y != NULL) { BN_free(y); y = NULL; } if (ec_private != NULL) { EC_KEY_free(ec_private); ec_private = NULL; } EVP_PKEY_free(private_key); return ret; } bool read_public_key(uint8_t *buf, size_t len, yh_algorithm *algo, uint8_t *bytes, size_t *bytes_len) { BIO *bio = BIO_new(BIO_s_mem()); if (bio == NULL) { return false; } (void) BIO_write(bio, buf, len); EVP_PKEY *pubkey = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL); BIO_free_all(bio); if (pubkey == NULL) { return false; } if (EVP_PKEY_base_id(pubkey) != EVP_PKEY_EC) { EVP_PKEY_free(pubkey); return false; } EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pubkey); EVP_PKEY_free(pubkey); if (ec == NULL) { return false; } const EC_GROUP *group = EC_KEY_get0_group(ec); int curve = EC_GROUP_get_curve_name(group); if (curve == NID_X9_62_prime256v1) { *algo = YH_ALGO_EC_P256; } else if (curve == NID_secp384r1) { *algo = YH_ALGO_EC_P384; } else if (curve == NID_secp521r1) { *algo = YH_ALGO_EC_P521; } else if (curve == NID_secp224r1) { *algo = YH_ALGO_EC_P224; #ifdef NID_brainpoolP256r1 } else if (curve == NID_brainpoolP256r1) { *algo = YH_ALGO_EC_BP256; #endif #ifdef NID_brainpoolP384r1 } else if (curve == NID_brainpoolP384r1) { *algo = YH_ALGO_EC_BP384; #endif #ifdef NID_brainpoolP512r1 } else if (curve == NID_brainpoolP512r1) { *algo = YH_ALGO_EC_BP512; #endif } else if (curve == NID_secp256k1) { *algo = YH_ALGO_EC_K256; } else { *algo = 0; } size_t data_len = i2o_ECPublicKey(ec, 0); if(data_len == 0 || data_len > *bytes_len) { EC_KEY_free(ec); return false; } (void) i2o_ECPublicKey(ec, &bytes); EC_KEY_free(ec); *bytes_len = data_len; return true; } void format_digest(uint8_t *digest, char *str, uint16_t len) { for (uint32_t i = 0; i < len; i++) { sprintf(str + (2 * i), "%02x", digest[i]); } str[2 * len] = '\0'; } int algo2nid(yh_algorithm algo) { switch (algo) { case YH_ALGO_EC_P256: case YH_ALGO_EC_P256_YUBICO_AUTHENTICATION: return NID_X9_62_prime256v1; case YH_ALGO_EC_P384: return NID_secp384r1; case YH_ALGO_EC_P521: return NID_secp521r1; case YH_ALGO_EC_P224: return NID_secp224r1; case YH_ALGO_EC_K256: return NID_secp256k1; #ifdef NID_brainpoolP256r1 case YH_ALGO_EC_BP256: return NID_brainpoolP256r1; #endif #ifdef NID_brainpoolP384r1 case YH_ALGO_EC_BP384: return NID_brainpoolP384r1; #endif #ifdef NID_brainpoolP512r1 case YH_ALGO_EC_BP512: return NID_brainpoolP512r1; #endif #ifdef NID_ED25519 case YH_ALGO_EC_ED25519: return NID_ED25519; #endif default: return 0; } } bool algo2type(yh_algorithm algorithm, yh_object_type *type) { switch (algorithm) { case YH_ALGO_RSA_PKCS1_SHA1: case YH_ALGO_RSA_PKCS1_SHA256: case YH_ALGO_RSA_PKCS1_SHA384: case YH_ALGO_RSA_PKCS1_SHA512: case YH_ALGO_RSA_PSS_SHA1: case YH_ALGO_RSA_PSS_SHA256: case YH_ALGO_RSA_PSS_SHA384: case YH_ALGO_RSA_PSS_SHA512: case YH_ALGO_RSA_2048: case YH_ALGO_RSA_3072: case YH_ALGO_RSA_4096: case YH_ALGO_EC_P224: case YH_ALGO_EC_P256: case YH_ALGO_EC_P384: case YH_ALGO_EC_P521: case YH_ALGO_EC_K256: case YH_ALGO_EC_BP256: case YH_ALGO_EC_BP384: case YH_ALGO_EC_BP512: case YH_ALGO_EC_ECDSA_SHA1: case YH_ALGO_EC_ECDH: case YH_ALGO_RSA_OAEP_SHA1: case YH_ALGO_RSA_OAEP_SHA256: case YH_ALGO_RSA_OAEP_SHA384: case YH_ALGO_RSA_OAEP_SHA512: case YH_ALGO_EC_ECDSA_SHA256: case YH_ALGO_EC_ECDSA_SHA384: case YH_ALGO_EC_ECDSA_SHA512: case YH_ALGO_EC_ED25519: *type = YH_ASYMMETRIC_KEY; break; case YH_ALGO_HMAC_SHA1: case YH_ALGO_HMAC_SHA256: case YH_ALGO_HMAC_SHA384: case YH_ALGO_HMAC_SHA512: *type = YH_HMAC_KEY; break; case YH_ALGO_AES128_CCM_WRAP: case YH_ALGO_AES192_CCM_WRAP: case YH_ALGO_AES256_CCM_WRAP: *type = YH_WRAP_KEY; break; case YH_ALGO_OPAQUE_DATA: case YH_ALGO_OPAQUE_X509_CERTIFICATE: *type = YH_OPAQUE; break; case YH_ALGO_TEMPLATE_SSH: *type = YH_TEMPLATE; break; case YH_ALGO_AES128_YUBICO_OTP: case YH_ALGO_AES192_YUBICO_OTP: case YH_ALGO_AES256_YUBICO_OTP: *type = YH_OTP_AEAD_KEY; break; case YH_ALGO_AES128_YUBICO_AUTHENTICATION: case YH_ALGO_EC_P256_YUBICO_AUTHENTICATION: *type = YH_AUTHENTICATION_KEY; break; case YH_ALGO_AES128: case YH_ALGO_AES192: case YH_ALGO_AES256: case YH_ALGO_AES_ECB: case YH_ALGO_AES_CBC: *type = YH_SYMMETRIC_KEY; break; case YH_ALGO_MGF1_SHA1: case YH_ALGO_MGF1_SHA256: case YH_ALGO_MGF1_SHA384: case YH_ALGO_MGF1_SHA512: default: return false; } return true; } int parse_NID(uint8_t *data, uint16_t data_len, const EVP_MD **md_type) { if (data_len >= sizeof(sha1oid) && memcmp(sha1oid, data, sizeof(sha1oid)) == 0) { *md_type = EVP_sha1(); return sizeof(sha1oid); } else if (data_len >= sizeof(sha256oid) && memcmp(sha256oid, data, sizeof(sha256oid)) == 0) { *md_type = EVP_sha256(); return sizeof(sha256oid); } else if (data_len >= sizeof(sha384oid) && memcmp(sha384oid, data, sizeof(sha384oid)) == 0) { *md_type = EVP_sha384(); return sizeof(sha384oid); } else if (data_len >= sizeof(sha512oid) && memcmp(sha512oid, data, sizeof(sha512oid)) == 0) { *md_type = EVP_sha512(); return sizeof(sha512oid); } else { *md_type = EVP_md_null(); return 0; } } bool read_file(FILE *fp, uint8_t *buf, size_t *buf_len) { size_t n = 0; size_t available = *buf_len; uint8_t *p = buf; do { n = fread(p, 1, available, fp); available -= n; p += n; } while (!feof(fp) && !ferror(fp) && available > 0); if (ferror(fp)) { return false; } if (!feof(fp) && available == 0) { uint8_t b[1]; n = fread(b, 1, 1, fp); if (!feof(fp)) { return false; } } *buf_len = p - buf; return true; } bool base64_decode(const char *in, uint8_t *out, size_t *len) { int ret; BIO *b64 = NULL; BIO *bio = NULL; b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { return false; } bio = BIO_new(BIO_s_mem()); if (bio == NULL) { BIO_free_all(b64); return false; } BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); BIO_push(b64, bio); (void) BIO_write(bio, in, strlen(in)); (void) BIO_flush(bio); ret = BIO_read(b64, out, *len); BIO_free_all(b64); if (ret <= 0) { return false; } else { *len = ret; return true; } } bool write_file(const uint8_t *buf, size_t buf_len, FILE *fp, format_t format) { const uint8_t *p = buf; uint8_t *data = NULL; size_t length = buf_len; size_t written = 0; BIO *b64 = NULL; if (format == _base64) { BIO *bio; BUF_MEM *bufferPtr; b64 = BIO_new(BIO_f_base64()); if (b64 == NULL) { return false; } bio = BIO_new(BIO_s_mem()); if (bio == NULL) { BIO_free_all(b64); return false; } bio = BIO_push(b64, bio); (void) BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL); (void) BIO_write(bio, buf, buf_len); (void) BIO_flush(bio); (void) BIO_get_mem_ptr(bio, &bufferPtr); p = (uint8_t *) bufferPtr->data; length = bufferPtr->length; } else if (format == _hex) { data = calloc(buf_len * 2 + 1, 1); if (data == NULL) { return false; } for (size_t i = 0; i < buf_len; i++) { sprintf((char *) data + i * 2, "%02x", buf[i]); } p = data; length = buf_len * 2; } else if (format == _PEM) { p = buf; length = buf_len; } do { written = fwrite(p, 1, length, fp); length -= written; p += written; } while (!feof(fp) && !ferror(fp) && length > 0); if (fp == stdout || fp == stderr) { if ( format != _binary ) { fprintf(fp, "\n"); } } if (b64 != NULL) { BIO_free_all(b64); b64 = NULL; } if (data != NULL) { free(data); data = NULL; } if (ferror(fp) || feof(fp)) { return false; } fflush(fp); return true; } bool write_ed25519_key(uint8_t *buf, size_t buf_len, FILE *fp, format_t format) { if (format == _base64 || format == _PEM) { uint8_t asn1[64]; uint8_t drop_newline; if (fp == stdout || fp == stderr) { drop_newline = 1; } else { drop_newline = 0; } if (sizeof(ed25519public_oid) + buf_len < buf_len || sizeof(ed25519public_oid) + buf_len > sizeof(asn1)) { return false; } memcpy(asn1, ed25519public_oid, sizeof(ed25519public_oid)); memcpy(asn1 + sizeof(ed25519public_oid), buf, buf_len); if (format == _PEM) { write_file(PEM_public_header, sizeof(PEM_public_header) - 1 - drop_newline, fp, _PEM); } write_file(asn1, sizeof(ed25519public_oid) + buf_len, fp, _base64); if (fp != stdout && fp != stderr) { uint8_t newline = '\n'; write_file(&newline, 1, fp, _PEM); } if (format == _PEM) { write_file(PEM_public_trailer, sizeof(PEM_public_trailer) - 1 - drop_newline, fp, _PEM); } } else if (format == _hex) { write_file(buf, buf_len, fp, _hex); if (fp != stdout && fp != stderr) { uint8_t newline = '\n'; write_file(&newline, 1, fp, _PEM); } } else { return false; // TODO(adma): _binary? } return true; } bool split_hmac_key(yh_algorithm algorithm, uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len) { uint8_t key[128 * 2] = {0}; uint8_t block_size; switch (algorithm) { case YH_ALGO_HMAC_SHA1: block_size = EVP_MD_block_size(EVP_sha1()); break; case YH_ALGO_HMAC_SHA256: block_size = EVP_MD_block_size(EVP_sha256()); break; case YH_ALGO_HMAC_SHA384: block_size = EVP_MD_block_size(EVP_sha384()); break; case YH_ALGO_HMAC_SHA512: block_size = EVP_MD_block_size(EVP_sha512()); break; default: return false; } if (in_len > block_size) { return false; // TODO(adma): hash the key } memcpy(key, in, in_len); for (uint8_t i = 0; i < block_size; i++) { out[i] = key[i] ^ 0x36; out[i + block_size] = key[i] ^ 0x5c; } *out_len = 2 * block_size; return true; } yubihsm-shell-2.6.0/common/ecdh.c0000644000175100001770000002074014666527773016242 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #ifdef _WIN32_BCRYPT #include #include #else #include #include #include #include #include "openssl-compat.h" #endif #include "ecdh.h" #ifdef _WIN32_BCRYPT static const uint8_t n_P256[] = "\xff\xff\xff\xff\x00\x00\x00\x00" "\xff\xff\xff\xff\xff\xff\xff\xff" "\xbc\xe6\xfa\xad\xa7\x17\x9e\x84" "\xf3\xb9\xca\xc2\xfc\x63\x25\x51"; static const BCRYPT_ALG_HANDLE curves[] = {NULL, BCRYPT_ECDH_P256_ALG_HANDLE}; static const ULONG lengths[] = {0, 256}; int ecdh_curve_p256(void) { return 1; } static int bn_cmp(const uint8_t *a, const uint8_t *b, size_t cb) { for (size_t i = 0; i < cb; i++) { if (a[i] < b[i]) return -1; if (a[i] > b[i]) return 1; } return 0; } static int validate_privkey(int curve, const uint8_t *privkey, size_t cb_privkey) { return curve == 1 && cb_privkey == 32 && bn_cmp(privkey, n_P256, 32) < 0; } int ecdh_calculate_public_key(int curve, const uint8_t *privkey, size_t cb_privkey, uint8_t *pubkey, size_t cb_pubkey) { int rc = 0; if (validate_privkey(curve, privkey, cb_privkey)) { uint8_t buf[256]; BCRYPT_ECCKEY_BLOB *blob = (BCRYPT_ECCKEY_BLOB *) buf; blob->dwMagic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; blob->cbKey = cb_privkey; memset(buf + sizeof(BCRYPT_ECCKEY_BLOB), 0, 2 * cb_privkey); memcpy(buf + sizeof(BCRYPT_ECCKEY_BLOB) + 2 * cb_privkey, privkey, cb_privkey); BCRYPT_KEY_HANDLE key; NTSTATUS status = BCryptImportKeyPair(curves[curve], NULL, BCRYPT_ECCPRIVATE_BLOB, &key, buf, sizeof(BCRYPT_ECCKEY_BLOB) + 3 * cb_privkey, BCRYPT_NO_KEY_VALIDATION); if (BCRYPT_SUCCESS(status)) { ULONG cb; status = BCryptExportKey(key, NULL, BCRYPT_ECCPUBLIC_BLOB, buf, sizeof(buf), &cb, 0); if (BCRYPT_SUCCESS(status) && cb_pubkey > 2 * blob->cbKey) { *pubkey = 4; memcpy(pubkey + 1, buf + sizeof(BCRYPT_ECCKEY_BLOB), 2 * blob->cbKey); rc = 1 + 2 * blob->cbKey; } BCryptDestroyKey(key); } } return rc; } int ecdh_generate_keypair(int curve, uint8_t *privkey, size_t cb_privkey, uint8_t *pubkey, size_t cb_pubkey) { int rc = 0; BCRYPT_KEY_HANDLE key; NTSTATUS status = BCryptGenerateKeyPair(curves[curve], &key, lengths[curve], 0); if (BCRYPT_SUCCESS(status)) { status = BCryptFinalizeKeyPair(key, 0); if (BCRYPT_SUCCESS(status)) { uint8_t buf[256]; ULONG cb; status = BCryptExportKey(key, NULL, BCRYPT_ECCPRIVATE_BLOB, buf, sizeof(buf), &cb, 0); BCRYPT_ECCKEY_BLOB *blob = (BCRYPT_ECCKEY_BLOB *) buf; if (BCRYPT_SUCCESS(status) && cb_privkey >= blob->cbKey && cb_pubkey > 2 * blob->cbKey) { *pubkey = 4; memcpy(pubkey + 1, buf + sizeof(BCRYPT_ECCKEY_BLOB), 2 * blob->cbKey); memcpy(privkey, buf + sizeof(BCRYPT_ECCKEY_BLOB) + 2 * blob->cbKey, blob->cbKey); rc = blob->cbKey; } } BCryptDestroyKey(key); } return rc; } int ecdh_calculate_secret(int curve, const uint8_t *privkey, size_t cb_privkey, const uint8_t *pubkey, size_t cb_pubkey, uint8_t *secret, size_t cb_secret) { int rc = 0; uint8_t buf[256]; BCRYPT_ECCKEY_BLOB *blob = (BCRYPT_ECCKEY_BLOB *) buf; blob->dwMagic = BCRYPT_ECDH_PRIVATE_P256_MAGIC; blob->cbKey = cb_privkey; memset(buf + sizeof(BCRYPT_ECCKEY_BLOB), 0, 2 * cb_privkey); memcpy(buf + sizeof(BCRYPT_ECCKEY_BLOB) + 2 * cb_privkey, privkey, cb_privkey); BCRYPT_KEY_HANDLE priv; NTSTATUS status = BCryptImportKeyPair(curves[curve], NULL, BCRYPT_ECCPRIVATE_BLOB, &priv, buf, sizeof(BCRYPT_ECCKEY_BLOB) + 3 * cb_privkey, BCRYPT_NO_KEY_VALIDATION); if (BCRYPT_SUCCESS(status)) { blob->dwMagic = BCRYPT_ECDH_PUBLIC_P256_MAGIC; blob->cbKey = cb_privkey; memcpy(buf + sizeof(BCRYPT_ECCKEY_BLOB), pubkey + 1, cb_pubkey - 1); BCRYPT_KEY_HANDLE pub; status = BCryptImportKeyPair(curves[curve], NULL, BCRYPT_ECCPUBLIC_BLOB, &pub, buf, sizeof(BCRYPT_ECCKEY_BLOB) + 2 * cb_privkey, 0); if (BCRYPT_SUCCESS(status)) { BCRYPT_SECRET_HANDLE sec; status = BCryptSecretAgreement(priv, pub, &sec, 0); if (BCRYPT_SUCCESS(status)) { ULONG cb; status = BCryptDeriveKey(sec, BCRYPT_KDF_RAW_SECRET, NULL, secret, cb_secret, &cb, 0); if (BCRYPT_SUCCESS(status)) { // BCRYPT_KDF_RAW_SECRET returns little-endian so reverse the array for (ULONG c = 0; c < cb / 2; c++) { uint8_t t = secret[c]; secret[c] = secret[cb - c - 1]; secret[cb - c - 1] = t; } rc = cb; } BCryptDestroySecret(sec); } BCryptDestroyKey(pub); } BCryptDestroyKey(priv); } return rc; } #else int ecdh_curve_p256(void) { return NID_X9_62_prime256v1; } int ecdh_calculate_public_key(int curve, const uint8_t *privkey, size_t cb_privkey, uint8_t *pubkey, size_t cb_pubkey) { BN_CTX *ctx = BN_CTX_new(); BIGNUM *order = BN_new(); BIGNUM *pvt = BN_bin2bn(privkey, cb_privkey, NULL); EC_GROUP *group = EC_GROUP_new_by_curve_name(curve); EC_POINT *pub = NULL; size_t cb = 0; if (ctx == NULL || order == NULL || pvt == NULL || group == NULL) { goto err; } EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); if (BN_is_zero(pvt) || !EC_GROUP_get_order(group, order, ctx) || BN_cmp(pvt, order) >= 0) { goto err; } pub = EC_POINT_new(group); if (pub == NULL || !EC_POINT_mul(group, pub, pvt, NULL, NULL, ctx)) { goto err; } cb = EC_POINT_point2oct(group, pub, POINT_CONVERSION_UNCOMPRESSED, pubkey, cb_pubkey, ctx); err: EC_POINT_free(pub); EC_GROUP_free(group); BN_free(pvt); BN_free(order); BN_CTX_free(ctx); return (int) cb; } int ecdh_generate_keypair(int curve, uint8_t *privkey, size_t cb_privkey, uint8_t *pubkey, size_t cb_pubkey) { EC_KEY *key = EC_KEY_new_by_curve_name(curve); if (key == NULL || !EC_KEY_generate_key(key)) { EC_KEY_free(key); return 0; } int len = BN_bn2binpad(EC_KEY_get0_private_key(key), privkey, cb_privkey); if (len <= 0) { EC_KEY_free(key); return 0; } size_t cb = EC_POINT_point2oct(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key), POINT_CONVERSION_UNCOMPRESSED, pubkey, cb_pubkey, NULL); if (cb == 0 || cb > cb_pubkey) { EC_KEY_free(key); return 0; } EC_KEY_free(key); return len; } int ecdh_calculate_secret(int curve, const uint8_t *privkey, size_t cb_privkey, const uint8_t *pubkey, size_t cb_pubkey, uint8_t *secret, size_t cb_secret) { EC_KEY *priv = EC_KEY_new_by_curve_name(curve); EC_KEY *pub = EC_KEY_new_by_curve_name(curve); EC_POINT *point = NULL; int len = 0; if (priv == NULL || pub == NULL || !EC_KEY_set_private_key(priv, BN_bin2bn(privkey, cb_privkey, NULL))) { goto err; } point = EC_POINT_new(EC_KEY_get0_group(pub)); if (point == NULL || !EC_POINT_oct2point(EC_KEY_get0_group(pub), point, pubkey, cb_pubkey, NULL)) { goto err; } if (!EC_KEY_set_public_key(pub, point) || !EC_KEY_check_key(pub)) { goto err; } len = ECDH_compute_key(secret, cb_secret, EC_KEY_get0_public_key(pub), priv, NULL); err: EC_POINT_free(point); EC_KEY_free(pub); EC_KEY_free(priv); return len > 0 ? len : 0; } #endif yubihsm-shell-2.6.0/common/parsing.h0000644000175100001770000000241714666527773017010 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YUBICOM_PARSING_H #define YUBICOM_PARSING_H #include #include #include #include "../common/platform-config.h" // NOTE(adma): those utility functions do not link against libyubihsm #define READ_STR_PROMPT_BASE "Enter %s: " #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif enum input_visibility { VISIBLE, HIDDEN_CHECKED, HIDDEN_UNCHECKED }; bool YH_INTERNAL read_string(const char *name, char *str_buf, size_t str_buf_len, enum input_visibility visibility); bool YH_INTERNAL hex_decode(const char *in, uint8_t *out, size_t *len); #endif yubihsm-shell-2.6.0/common/openssl-compat.h0000644000175100001770000000342714666527773020313 0ustar runnerdocker/* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #ifndef LIBCRYPTO_COMPAT_H #define LIBCRYPTO_COMPAT_H #include #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) #include #include #include #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif #if (OPENSSL_VERSION_NUMBER < 0x10100000L) int YH_INTERNAL RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d); void YH_INTERNAL RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d); void YH_INTERNAL RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q); void YH_INTERNAL RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp); void YH_INTERNAL ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps); int YH_INTERNAL ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s); const YH_INTERNAL STACK_OF(X509_EXTENSION) * X509_get0_extensions(const X509 *x); ASN1_OBJECT YH_INTERNAL *X509_EXTENSION_get_object(X509_EXTENSION *ex); ASN1_OCTET_STRING YH_INTERNAL *X509_EXTENSION_get_data(X509_EXTENSION *ex); #endif /* OPENSSL_VERSION_NUMBER */ int YH_INTERNAL BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen); #endif /* OPENSSL_VERSION_NUMBER */ #endif /* LIBCRYPTO_COMPAT_H */ yubihsm-shell-2.6.0/common/hash.c0000644000175100001770000002030014666527773016252 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifdef _WIN32_BCRYPT #include #include #else #include #endif #include #include "hash.h" #include "insecure_memzero.h" typedef struct _hash_ctx { #ifdef _WIN32_BCRYPT BCRYPT_ALG_HANDLE hAlg; BCRYPT_HASH_HANDLE hHash; PBYTE pbHashObj; bool fFinal; size_t cbHash; #else EVP_MD_CTX *mdctx; const EVP_MD *md; #endif } _hash_ctx, *hash_ctx; #ifndef _WIN32_BCRYPT const YH_INTERNAL EVP_MD *get_hash(hash_t hash) { switch (hash) { case _NONE: return NULL; case _SHA1: return EVP_sha1(); case _SHA256: return EVP_sha256(); case _SHA384: return EVP_sha384(); case _SHA512: return EVP_sha512(); default: return NULL; } } #else LPCWSTR YH_INTERNAL get_hash(hash_t hash) { switch (hash) { case _NONE: return NULL; case _SHA1: return BCRYPT_SHA1_ALGORITHM; case _SHA256: return BCRYPT_SHA256_ALGORITHM; case _SHA384: return BCRYPT_SHA384_ALGORITHM; case _SHA512: return BCRYPT_SHA512_ALGORITHM; default: return NULL; } } #endif bool hash_bytes(const uint8_t *in, size_t len, hash_t hash, uint8_t *out, size_t *out_len) { #ifndef _WIN32_BCRYPT const EVP_MD *md; unsigned int d_len = 0; bool ret = false; md = get_hash(hash); if (md == NULL) { return false; } if (EVP_MD_size(md) < 0 || *out_len < (size_t) EVP_MD_size(md)) { return false; } EVP_MD_CTX *mdctx = EVP_MD_CTX_create(); if ((EVP_DigestInit_ex(mdctx, md, NULL)) != 1) { goto hash_bytes_exit; } if ((EVP_DigestUpdate(mdctx, in, len)) != 1) { goto hash_bytes_exit; } if ((EVP_DigestFinal_ex(mdctx, out, &d_len)) != 1) { goto hash_bytes_exit; } ret = true; hash_bytes_exit: *out_len = d_len; EVP_MD_CTX_destroy(mdctx); return ret; #else bool res = false; NTSTATUS status = 0; LPCWSTR alg = NULL; BCRYPT_ALG_HANDLE hAlg = 0; BCRYPT_HASH_HANDLE hHash = 0; DWORD cbHashObj = 0; DWORD cbHash = 0; DWORD cbData = 0; PBYTE pbHashObj = NULL; alg = get_hash(hash); if (alg == NULL) { return false; } if (!BCRYPT_SUCCESS(status = BCryptOpenAlgorithmProvider(&hAlg, alg, NULL, 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptGetProperty(hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE) &cbHashObj, sizeof(DWORD), &cbData, 0))) { goto cleanup; } if (!(pbHashObj = (PBYTE) malloc(cbHashObj))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptGetProperty(hAlg, BCRYPT_HASH_LENGTH, (PBYTE) &cbHash, sizeof(DWORD), &cbData, 0))) { goto cleanup; } if (*out_len < cbHash) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptCreateHash(hAlg, &hHash, pbHashObj, cbHashObj, NULL, 0, 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptHashData(hHash, (PBYTE) in, len, 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptFinishHash(hHash, out, cbHash, 0))) { goto cleanup; } *out_len = cbHash; res = true; cleanup: if (pbHashObj) { free(pbHashObj); } if (hHash) { BCryptDestroyHash(hHash); } if (hAlg) { BCryptCloseAlgorithmProvider(hAlg, 0); } return res; #endif } bool hash_create(_hash_ctx **ctx, hash_t hash) { bool res = false; _hash_ctx *ctx_temp = NULL; #ifdef _WIN32_BCRYPT NTSTATUS status = 0; LPCWSTR alg = NULL; DWORD cbHashObj = 0; DWORD cbHash = 0; DWORD cbData = 0; #else const EVP_MD *md = NULL; #endif if (!ctx) { return false; } if (*ctx) { return false; } if (!(ctx_temp = (_hash_ctx *) malloc(sizeof(_hash_ctx)))) { return false; } insecure_memzero(ctx_temp, sizeof(_hash_ctx)); #ifdef _WIN32_BCRYPT if (!(alg = get_hash(hash))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptOpenAlgorithmProvider(&(ctx_temp->hAlg), alg, NULL, 0))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptGetProperty(ctx_temp->hAlg, BCRYPT_OBJECT_LENGTH, (PBYTE) &cbHashObj, sizeof(DWORD), &cbData, 0))) { goto cleanup; } if (!(ctx_temp->pbHashObj = (PBYTE) malloc(cbHashObj))) { goto cleanup; } if (!BCRYPT_SUCCESS(status = BCryptGetProperty(ctx_temp->hAlg, BCRYPT_HASH_LENGTH, (PBYTE) &cbHash, sizeof(DWORD), &cbData, 0))) { goto cleanup; } ctx_temp->cbHash = (size_t) cbHash; if (!BCRYPT_SUCCESS(status = BCryptCreateHash(ctx_temp->hAlg, &(ctx_temp->hHash), ctx_temp->pbHashObj, cbHashObj, NULL, 0, BCRYPT_HASH_REUSABLE_FLAG))) { goto cleanup; } ctx_temp->fFinal = true; #else if (!(md = get_hash(hash))) { goto cleanup; } if (!(ctx_temp->mdctx = EVP_MD_CTX_create())) { goto cleanup; } ctx_temp->md = md; #endif /* set output parameters */ *ctx = ctx_temp; ctx_temp = NULL; res = true; cleanup: if (ctx_temp) { #ifdef _WIN32_BCRYPT if (ctx_temp->hHash) { BCryptDestroyHash(ctx_temp->hHash); } if (ctx_temp->pbHashObj) { free(ctx_temp->pbHashObj); } if (ctx_temp->hAlg) { BCryptCloseAlgorithmProvider(ctx_temp->hAlg, 0); } #endif free(ctx_temp); } return res; } bool hash_init(_hash_ctx *ctx) { if (!ctx) { return false; } #ifdef _WIN32_BCRYPT /* finalize the hash, it should be marked as reusable */ if (!ctx->fFinal) { size_t cbHash = ctx->cbHash; uint8_t *temp = (uint8_t *) malloc(cbHash); if (temp) { bool res = hash_final(ctx, temp, &cbHash); free(temp); return res; } } #else if (EVP_DigestInit_ex(ctx->mdctx, ctx->md, NULL) != 1) { return false; } #endif return true; } bool hash_update(_hash_ctx *ctx, const uint8_t *in, size_t cb_in) { #ifdef _WIN32_BCRYPT NTSTATUS status = 0; #endif if (!ctx) { return false; } #ifdef _WIN32_BCRYPT if (!ctx->hHash) { return false; } ctx->fFinal = true; if (!BCRYPT_SUCCESS(status = BCryptHashData(ctx->hHash, (PBYTE) in, cb_in, 0))) { return false; } #else if (!(ctx->mdctx)) { return false; } if (EVP_DigestUpdate(ctx->mdctx, in, cb_in) != 1) { return false; } #endif return true; } bool hash_final(_hash_ctx *ctx, uint8_t *out, size_t *pcb_out) { #ifdef _WIN32_BCRYPT NTSTATUS status = 0; #else unsigned int d_len = 0; #endif if (!ctx) { return false; } #ifdef _WIN32_BCRYPT if (!(ctx->hHash)) { return false; } if (*pcb_out < ctx->cbHash) { return false; } if (!BCRYPT_SUCCESS(status = BCryptFinishHash(ctx->hHash, out, ctx->cbHash, 0))) { return false; } *pcb_out = ctx->cbHash; #else if (EVP_DigestFinal_ex(ctx->mdctx, out, &d_len) != 1) { *pcb_out = 0; return false; } *pcb_out = d_len; #endif return true; } bool hash_destroy(_hash_ctx *ctx) { if (!ctx) { return false; } #ifdef _WIN32_BCRYPT if (ctx->hHash) { BCryptDestroyHash(ctx->hHash); } if (ctx->pbHashObj) { free(ctx->pbHashObj); } if (ctx->hAlg) { BCryptCloseAlgorithmProvider(ctx->hAlg, 0); } #else if (ctx->mdctx) { EVP_MD_CTX_destroy(ctx->mdctx); } #endif free(ctx); return true; } yubihsm-shell-2.6.0/common/platform-config.h0000644000175100001770000000310414666530015020405 0ustar runnerdocker/* * 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: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * 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 * OWNER 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 YUBIHSM_CONFIG_H #define YUBIHSM_CONFIG_H #ifdef __cplusplus extern "C" { #endif /* #undef _WIN32_BCRYPT */ /* #undef __WIN32 */ /* #undef _WIN32 */ /* #undef _MSVC */ #ifdef __cplusplus } #endif #endif yubihsm-shell-2.6.0/common/insecure_memzero.h0000644000175100001770000000204714666527773020717 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YUBICOM_MEMZERO_H #define YUBICOM_MEMZERO_H #ifdef _WIN32 #include #define insecure_memzero(buf, len) SecureZeroMemory(buf, len) #elif HAVE_MEMSET_S #include #define insecure_memzero(buf, len) memset_s(buf, len, 0, len) #elif HAVE_EXPLICIT_BZERO #include #define insecure_memzero(buf, len) explicit_bzero(buf, len) #else #include #define insecure_memzero(buf, len) OPENSSL_cleanse(buf, len) #endif #endif yubihsm-shell-2.6.0/common/rand.c0000644000175100001770000000227414666527773016265 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "rand.h" #ifdef _WIN32_BCRYPT #include #include #include #else #include #endif bool rand_generate(uint8_t *buf, size_t cb_buf) { #ifdef _WIN32_BCRYPT NTSTATUS status = STATUS_SUCCESS; BCRYPT_ALG_HANDLE hAlg = 0; if (!BCRYPT_SUCCESS( status = BCryptOpenAlgorithmProvider(&hAlg, BCRYPT_RNG_ALGORITHM, NULL, 0))) { return false; } status = BCryptGenRandom(hAlg, buf, (ULONG) cb_buf, 0); BCryptCloseAlgorithmProvider(hAlg, 0); return BCRYPT_SUCCESS(status); #else return (1 == RAND_bytes(buf, cb_buf)); #endif } yubihsm-shell-2.6.0/common/time_win.h0000644000175100001770000000144014666527773017153 0ustar runnerdocker/* * Copyright 2020 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YUBIHSM_SHELL_TIME_WIN_H #define YUBIHSM_SHELL_TIME_WIN_H #include #ifdef _MSVC struct timeval; int gettimeofday(struct timeval *tv, void *tzp); #endif #endif // YUBIHSM_SHELL_TIME_WIN_H yubihsm-shell-2.6.0/common/debug.h0000644000175100001770000000537514666527773016441 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef DEBUG_H #define DEBUG_H #include "../common/platform-config.h" #include "time_win.h" #ifdef _MSVC #include #endif #ifdef __linux__ #define ANSI_RED "\x1b[31m" #define ANSI_GREEN "\x1b[32m" #define ANSI_YELLOW "\x1b[33m" #define ANSI_BLUE "\x1b[34m" #define ANSI_MAGENTA "\x1b[35m" #define ANSI_CYAN "\x1b[36m" #define ANSI_RESET "\x1b[0m" #else #define ANSI_RED "" #define ANSI_GREEN "" #define ANSI_YELLOW "" #define ANSI_BLUE "" #define ANSI_MAGENTA "" #define ANSI_CYAN "" #define ANSI_RESET "" #endif #define __FILENAME__ \ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #ifdef _MSVC #define localtime_r(a, b) localtime_s(b, a) #endif #define D(var, file, col, who, lev, ...) \ if (var) { \ struct timeval _tv; \ struct tm _tm; \ char _tbuf[20]; \ time_t _tsecs; \ gettimeofday(&_tv, NULL); \ _tsecs = _tv.tv_sec; \ localtime_r(&_tsecs, &_tm); \ strftime(_tbuf, 20, "%H:%M:%S", &_tm); \ fprintf(file, "[" col who " - " lev ANSI_RESET " %s.%06ld] ", _tbuf, \ (long) _tv.tv_usec); \ fprintf(file, "%s:%d (%s): ", __FILENAME__, __LINE__, __func__); \ fprintf(file, __VA_ARGS__); \ } #define DLN(var, file, col, who, lev, ...) \ if (var) { \ D(var, file != NULL ? file : stderr, col, who, lev, __VA_ARGS__); \ fprintf(file != NULL ? file : stderr, "\n"); \ } #endif yubihsm-shell-2.6.0/common/pkcs5.h0000644000175100001770000000241314666527773016366 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* pkcs5.h ** ** Implements platform specific PKCS5 operations */ #ifndef _YUBICOM_PKCS5_H_ #define _YUBICOM_PKCS5_H_ #include #include #include #include "hash.h" #ifdef __cplusplus extern "C" { #endif #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif bool YH_INTERNAL pkcs5_pbkdf2_hmac(const uint8_t *password, size_t cb_password, const uint8_t *salt, size_t cb_salt, uint64_t iterations, hash_t hash, uint8_t *key, size_t cb_key); #ifdef __cplusplus } #endif #endif /* _YUBICOM_PKCS5_H_ */ yubihsm-shell-2.6.0/common/util.h0000644000175100001770000000456614666527773016331 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef YUBICOM_UTIL_H #define YUBICOM_UTIL_H #include #include #include #include #include #include "../common/platform-config.h" typedef enum { _base64, _binary, _hex, _PEM, } format_t; #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif bool YH_INTERNAL set_component(uint8_t *in_ptr, const BIGNUM *bn, int32_t element_len); bool YH_INTERNAL read_private_key(uint8_t *buf, size_t len, yh_algorithm *algo, uint8_t *bytes, size_t *bytes_len, bool internal_repr); bool YH_INTERNAL read_public_key(uint8_t *buf, size_t len, yh_algorithm *algo, uint8_t *bytes, size_t *bytes_len); void YH_INTERNAL format_digest(uint8_t *digest, char *str, uint16_t len); int YH_INTERNAL algo2nid(yh_algorithm algo); bool YH_INTERNAL algo2type(yh_algorithm algorithm, yh_object_type *type); int YH_INTERNAL parse_NID(uint8_t *data, uint16_t data_len, const EVP_MD **md_type); bool YH_INTERNAL read_file(FILE *fp, uint8_t *buf, size_t *buf_len); bool YH_INTERNAL write_file(const uint8_t *buf, size_t buf_len, FILE *fp, format_t format); bool YH_INTERNAL read_ed25519_key(uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); bool YH_INTERNAL write_ed25519_key(uint8_t *buf, size_t buf_len, FILE *fp, format_t format); bool YH_INTERNAL base64_decode(const char *in, uint8_t *out, size_t *len); bool YH_INTERNAL split_hmac_key(yh_algorithm algorithm, uint8_t *in, size_t in_len, uint8_t *out, size_t *out_len); #endif yubihsm-shell-2.6.0/common/time_win.c0000644000175100001770000000163514666527773017154 0ustar runnerdocker/* * Copyright 2020 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "time_win.h" int gettimeofday(struct timeval *tv, void *tzp) { // There's no equivalent implementation of gettimeofday() on Window struct timespec ts = {0}; if (timespec_get(&ts, TIME_UTC)) { tv->tv_sec = (long) ts.tv_sec; tv->tv_usec = ts.tv_nsec / 1000; return 0; } return -1; } yubihsm-shell-2.6.0/common/ecdh.h0000644000175100001770000000331014666527773016241 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* ecdh.h ** ** Implements platform specific ECDH operations */ #ifndef _YUBICOM_ECDH_H_ #define _YUBICOM_ECDH_H_ #include #include #include "../common/platform-config.h" #ifdef __cplusplus extern "C" { #endif #ifndef __WIN32 #define YH_INTERNAL __attribute__((visibility("hidden"))) #else #define YH_INTERNAL #endif int YH_INTERNAL ecdh_curve_p256(void); int YH_INTERNAL ecdh_calculate_public_key(int curve, const uint8_t *privkey, size_t cb_privkey, uint8_t *pubkey, size_t cb_pubkey); int YH_INTERNAL ecdh_generate_keypair(int curve, uint8_t *privkey, size_t cb_privkey, uint8_t *pubkey, size_t cb_pubkey); int YH_INTERNAL ecdh_calculate_secret(int curve, const uint8_t *privkey, size_t cb_privkey, const uint8_t *pubkey, size_t cb_pubkey, uint8_t *secret, size_t cb_secret); #ifdef __cplusplus } #endif #endif /* _YUBICOM_ECDH_H_ */ yubihsm-shell-2.6.0/common/openssl-compat.c0000644000175100001770000000525114666527773020303 0ustar runnerdocker/* * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ #include "openssl-compat.h" extern int make_iso_compilers_happy; #if (OPENSSL_VERSION_NUMBER < 0x10100000L) || defined(LIBRESSL_VERSION_NUMBER) #include #if (OPENSSL_VERSION_NUMBER < 0x10100000L) int RSA_set0_key(RSA *r, BIGNUM *n, BIGNUM *e, BIGNUM *d) { /* If the fields n and e in r are NULL, the corresponding input * parameters MUST be non-NULL for n and e. d may be * left NULL (in case only the public key is used). */ if ((r->n == NULL && n == NULL) || (r->e == NULL && e == NULL)) return 0; if (n != NULL) { BN_free(r->n); r->n = n; } if (e != NULL) { BN_free(r->e); r->e = e; } if (d != NULL) { BN_free(r->d); r->d = d; } return 1; } void RSA_get0_key(const RSA *r, const BIGNUM **n, const BIGNUM **e, const BIGNUM **d) { if (n != NULL) *n = r->n; if (e != NULL) *e = r->e; if (d != NULL) *d = r->d; } void RSA_get0_factors(const RSA *r, const BIGNUM **p, const BIGNUM **q) { if (p != NULL) *p = r->p; if (q != NULL) *q = r->q; } void RSA_get0_crt_params(const RSA *r, const BIGNUM **dmp1, const BIGNUM **dmq1, const BIGNUM **iqmp) { if (dmp1 != NULL) *dmp1 = r->dmp1; if (dmq1 != NULL) *dmq1 = r->dmq1; if (iqmp != NULL) *iqmp = r->iqmp; } int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) { if ((sig->r == NULL && r == NULL) || (sig->s == NULL && s == NULL)) { return 0; } if (r != NULL) { BN_free(sig->r); sig->r = r; } if (s != NULL) { BN_free(sig->s); sig->s = s; } return 1; } void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { if (pr != NULL) { *pr = sig->r; } if (ps != NULL) { *ps = sig->s; } } const STACK_OF(X509_EXTENSION) * X509_get0_extensions(const X509 *x) { return x->cert_info->extensions; } ASN1_OBJECT *X509_EXTENSION_get_object(X509_EXTENSION *ex) { return ex->object; } ASN1_OCTET_STRING *X509_EXTENSION_get_data(X509_EXTENSION *ex) { return ex->value; } #endif /* OPENSSL_VERSION_NUMBER */ int BN_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen) { int n = BN_num_bytes(a); if (n < 0 || n > tolen) { return -1; } memset(to, 0, tolen - n); if (BN_bn2bin(a, to + tolen - n) < 0) { return -1; } return tolen; } #endif /* OPENSSL_VERSION_NUMBER */ yubihsm-shell-2.6.0/common/pkcs5.c0000644000175100001770000000373214666527773016366 0ustar runnerdocker/* * Copyright 2015-2018 Yubico AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "pkcs5.h" #ifdef _WIN32_BCRYPT #include #include #else #include #endif bool pkcs5_pbkdf2_hmac(const uint8_t *password, size_t cb_password, const uint8_t *salt, size_t cb_salt, uint64_t iterations, hash_t hash, uint8_t *key, size_t cb_key) { bool res = false; #ifdef _WIN32_BCRYPT NTSTATUS status = 0; LPCWSTR alg = NULL; BCRYPT_ALG_HANDLE hAlg = 0; if (!(alg = get_hash(hash))) { goto cleanup; } if (!BCRYPT_SUCCESS( status = BCryptOpenAlgorithmProvider(&hAlg, alg, NULL, BCRYPT_ALG_HANDLE_HMAC_FLAG))) { goto cleanup; } if (!BCRYPT_SUCCESS( status = BCryptDeriveKeyPBKDF2(hAlg, (PUCHAR) password, (ULONG) cb_password, (PUCHAR) salt, (ULONG) cb_salt, iterations, key, (ULONG) cb_key, 0))) { goto cleanup; } res = true; cleanup: if (hAlg) { BCryptCloseAlgorithmProvider(hAlg, 0); } #else const EVP_MD *md = NULL; if (!(md = get_hash(hash))) { return false; } /* for some reason openssl always returns 1 for PBKDF2 */ if (1 != PKCS5_PBKDF2_HMAC((const char *) password, cb_password, salt, cb_salt, iterations, md, cb_key, key)) { return false; } res = true; #endif return res; } yubihsm-shell-2.6.0/lib/0000755000175100001770000000000014666527773014446 5ustar runnerdockeryubihsm-shell-2.6.0/lib/CMakeLists.txt0000644000175100001770000002020314666527773017203 0ustar runnerdocker# # Copyright 2015-2018 Yubico AB # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # if(${WIN32_BCRYPT}) else(${WIN32_BCRYPT}) include(${CMAKE_SOURCE_DIR}/cmake/openssl.cmake) find_libcrypto() endif(${WIN32_BCRYPT}) if(MSVC) set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS TRUE) endif() set ( SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/../aes_cmac/aes.c ${CMAKE_CURRENT_SOURCE_DIR}/../aes_cmac/aes_cmac.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/hash.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/pkcs5.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/rand.c ${CMAKE_CURRENT_SOURCE_DIR}/../common/ecdh.c error.c lib_util.c yubihsm.c ) if(MSVC) set(SOURCE ${SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/../common/time_win.c) endif(MSVC) set(STATIC_SOURCE ${SOURCE}) if(NOT ${WIN32_BCRYPT}) set(SOURCE ${SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/../common/openssl-compat.c) endif(NOT ${WIN32_BCRYPT}) set (STATIC_SOURCE ${SOURCE}) if(WIN32) set(ADDITIONAL_LIBRARY ws2_32) set ( HTTP_SOURCE yubihsm_winhttp.c lib_util.c ${CMAKE_CURRENT_BINARY_DIR}/version_winhttp.rc ${CMAKE_CURRENT_SOURCE_DIR}/../common/time_win.c ) set ( USB_SOURCE yubihsm_usb.c yubihsm_winusb.c lib_util.c ${CMAKE_CURRENT_BINARY_DIR}/version_winusb.rc ${CMAKE_CURRENT_SOURCE_DIR}/../common/time_win.c ) set(HTTP_LIBRARY winhttp ws2_32) set(USB_LIBRARY winusb ws2_32 setupapi) if(${WIN32_BCRYPT}) set (CRYPT_LIBRARY bcrypt) add_definitions (-D_WIN32_BCRYPT) else(${WIN32_BCRYPT}) set(CRYPT_LIBRARY ${LIBCRYPTO_LDFLAGS}) endif(${WIN32_BCRYPT}) list(APPEND SOURCE ${CMAKE_CURRENT_BINARY_DIR}/version.rc) list(APPEND STATIC_SOURCE yubihsm_winusb.c yubihsm_usb.c yubihsm_winhttp.c) else(WIN32) set(ADDITIONAL_LIBRARY -ldl) set ( USB_SOURCE yubihsm_usb.c yubihsm_libusb.c lib_util.c ) set ( HTTP_SOURCE yubihsm_curl.c lib_util.c ) set(HTTP_LIBRARY ${LIBCURL_LDFLAGS}) set(USB_LIBRARY ${LIBUSB_LDFLAGS}) set(CRYPT_LIBRARY ${LIBCRYPTO_LDFLAGS}) list(APPEND STATIC_SOURCE yubihsm_libusb.c yubihsm_usb.c yubihsm_curl.c) endif(WIN32) include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ${LIBCRYPTO_INCLUDEDIR} ${LIBCURL_INCLUDEDIR} ) add_library (yubihsm SHARED ${SOURCE}) add_library (yubihsm_usb SHARED ${USB_SOURCE}) add_library (yubihsm_http SHARED ${HTTP_SOURCE}) set_target_properties(yubihsm PROPERTIES BUILD_RPATH "${CMAKE_BINARY_DIR}/lib") set_target_properties (yubihsm PROPERTIES VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}" SOVERSION ${yubihsm_shell_VERSION_MAJOR}) set_target_properties (yubihsm_usb PROPERTIES VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}" SOVERSION ${yubihsm_shell_VERSION_MAJOR}) set_target_properties (yubihsm_http PROPERTIES VERSION "${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}" SOVERSION ${yubihsm_shell_VERSION_MAJOR}) if(MSVC) set_target_properties(yubihsm PROPERTIES OUTPUT_NAME libyubihsm) set_target_properties(yubihsm_usb PROPERTIES OUTPUT_NAME libyubihsm_usb) set_target_properties(yubihsm_http PROPERTIES OUTPUT_NAME libyubihsm_http) else(MSVC) set_target_properties(yubihsm PROPERTIES OUTPUT_NAME yubihsm) set_target_properties(yubihsm_usb PROPERTIES OUTPUT_NAME yubihsm_usb) set_target_properties(yubihsm_http PROPERTIES OUTPUT_NAME yubihsm_http) endif(MSVC) if (ENABLE_STATIC) add_library (yubihsm_static STATIC ${STATIC_SOURCE}) set_target_properties (yubihsm_static PROPERTIES POSITION_INDEPENDENT_CODE on OUTPUT_NAME yubihsm) set_target_properties (yubihsm_static PROPERTIES COMPILE_FLAGS "-DSTATIC " ) if(MSVC) set_property(TARGET yubihsm_static PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") endif(MSVC) add_coverage (yubihsm_static) endif() if(${WIN32}) else(${WIN32}) if(${LIBUSB_VERSION} VERSION_LESS 1.0.16) set(LIBUSB_CFLAGS "${LIBUSB_CFLAGS} -DNO_LIBUSB_STRERROR") endif() set_target_properties (yubihsm_usb PROPERTIES COMPILE_FLAGS ${LIBUSB_CFLAGS}) if(ENABLE_STATIC) set_property(TARGET yubihsm_static APPEND_STRING PROPERTY COMPILE_FLAGS ${LIBUSB_CFLAGS}) endif(ENABLE_STATIC) endif(${WIN32}) add_coverage (yubihsm) add_coverage (yubihsm_usb) add_coverage (yubihsm_http) add_definitions (-DVERSION="${yubihsm_shell_VERSION_MAJOR}.${yubihsm_shell_VERSION_MINOR}.${yubihsm_shell_VERSION_PATCH}") add_definitions (-DSOVERSION="${yubihsm_shell_VERSION_MAJOR}") target_link_libraries (yubihsm ${CRYPT_LIBRARY} ${ADDITIONAL_LIBRARY}) target_link_libraries (yubihsm_usb ${USB_LIBRARY}) target_link_libraries (yubihsm_http ${HTTP_LIBRARY}) if(ENABLE_STATIC) target_link_libraries (yubihsm_static ${CRYPT_LIBRARY} ${ADDITIONAL_LIBRARY} ${HTTP_LIBRARY} ${USB_LIBRARY}) endif(ENABLE_STATIC) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/yubihsm.pc.in ${CMAKE_CURRENT_BINARY_DIR}/yubihsm.pc @ONLY) configure_file(${CMAKE_SOURCE_DIR}/common/platform-config.h.in ${CMAKE_SOURCE_DIR}/common/platform-config.h @ONLY) if(WIN32) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version_winhttp.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version_winhttp.rc @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version_winusb.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version_winusb.rc @ONLY) endif(WIN32) install( TARGETS yubihsm ARCHIVE DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} LIBRARY DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} RUNTIME DESTINATION ${YUBIHSM_INSTALL_BIN_DIR}) install( TARGETS yubihsm_usb ARCHIVE DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} LIBRARY DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} RUNTIME DESTINATION ${YUBIHSM_INSTALL_BIN_DIR}) install( TARGETS yubihsm_http ARCHIVE DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} LIBRARY DESTINATION ${YUBIHSM_INSTALL_LIB_DIR} RUNTIME DESTINATION ${YUBIHSM_INSTALL_BIN_DIR}) install(FILES yubihsm.h DESTINATION ${YUBIHSM_INSTALL_INC_DIR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/yubihsm.pc DESTINATION ${YUBIHSM_INSTALL_PKGCONFIG_DIR}) add_subdirectory (tests) add_test( NAME parsing COMMAND test_parsing WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib/tests/ ) add_test( NAME pbkdf2 COMMAND test_pbkdf2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/lib/tests/ ) add_test( NAME attest COMMAND attest WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME generate_ec COMMAND generate_ec ) add_test( NAME generate_hmac COMMAND generate_hmac ) add_test( NAME import_authkey COMMAND import_authkey ) add_test( NAME import_rsa COMMAND import_rsa WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME info COMMAND info ) add_test( NAME wrap COMMAND wrap ) add_test( NAME wrap_data COMMAND wrap_data ) add_test( NAME yubico_otp COMMAND yubico_otp ) add_test( NAME echo COMMAND echo ) add_test( NAME asym_auth COMMAND asym_auth ) add_test( NAME import_ec COMMAND import_ec WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME generate_rsa COMMAND generate_rsa ) add_test( NAME logs COMMAND logs ) add_test( NAME ssh COMMAND ssh WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME decrypt_rsa COMMAND decrypt_rsa WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME decrypt_ec COMMAND decrypt_ec ) add_test( NAME import_ed COMMAND import_ed WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/examples/ ) add_test( NAME change_authkey COMMAND change_authkey ) add_test( NAME encrypt_aes COMMAND encrypt_aes WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/examples" ) set_tests_properties(encrypt_aes PROPERTIES SKIP_RETURN_CODE 64) yubihsm-shell-2.6.0/lib/Doxyfile0000644000175100001770000031732514666527773016167 0ustar runnerdocker# Doxyfile 1.8.11 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "libyubihsm" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify a logo or an icon that is included # in the documentation. The maximum height of the logo should not exceed 55 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy # the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = doxygen # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII # characters to appear in the names of generated files. If set to NO, non-ASCII # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode # U+3044. # The default value is: NO. ALLOW_UNICODE_NAMES = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, # Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), # Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, # Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, # Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, # Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, # Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = YES # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new # page for each member. If set to NO, the documentation of a member will be part # of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: # FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: # Fortran. In the later case the parser tries to guess whether the code is fixed # or free formatted code, this is the default for Fortran type files), VHDL. For # instance to make doxygen treat .inc files as Fortran files (default is PHP), # and .f files as C (default is Fortran), use: inc=Fortran f=C. # # Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by putting a % sign in front of the word or # globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # If one adds a struct or class to a group and this option is enabled, then also # any nested class or struct is added to the same group. By default this option # is disabled and one has to add nested compounds explicitly via \ingroup. # The default value is: NO. GROUP_NESTED_COMPOUNDS = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined # locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO, these classes will be included in the various overviews. This option # has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will # append additional text to a page's title, such as Class Reference. If set to # YES the compound reference will be hidden. # The default value is: NO. HIDE_COMPOUND_REFERENCE= NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = NO # If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each # grouped member an include statement to the documentation, telling the reader # which file to include in order to use the member. # The default value is: NO. SHOW_GROUPED_MEMB_INC = NO # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = YES # The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo # list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test # list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES, the # list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = YES # If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = YES # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO, doxygen will only warn about wrong or incomplete # parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = YES # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when # a warning is encountered. # The default value is: NO. WARN_AS_ERROR = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = yubihsm.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # read by doxygen. # # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, # *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, # *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f, *.for, *.tcl, # *.vhd, *.vhdl, *.ucf, *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. # # Note that for custom extensions or not directly supported extensions you also # need to set EXTENSION_MAPPING for the extension otherwise the files are not # properly processed by doxygen. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES # If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the # clang parser (see: http://clang.llvm.org/) for more accurate parsing at the # cost of reduced performance. This can be particularly helpful with template # rich C++ code for which doxygen's built-in parser lacks the necessary type # information. # Note: The availability of this option depends on whether or not doxygen was # generated with the -Duse-libclang=ON option for CMake. # The default value is: NO. CLANG_ASSISTED_PARSING = NO # If clang assisted parsing is enabled you can provide the compiler with command # line options that you would normally use when invoking the compiler. Note that # the include paths will already be set by doxygen for the files and directories # specified with INPUT and INCLUDE_PATH. # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. CLANG_OPTIONS = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined # cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefore more robust against future updates. # Doxygen will copy the style sheet files to the output directory. # Note: The order of the extra style sheet files is of importance (e.g. the last # style sheet in the list overrules the setting of the previous ones in the # list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to YES can help to show when doxygen was last run and thus if the # documentation is up to date. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated # (YES) or that it should be included in the main .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it # enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /