pax_global_header00006660000000000000000000000064141316026030014506gustar00rootroot0000000000000052 comment=ebda3f788251371a2878ee432fa6b49d81d3c8a7 libzpc-1.0.0/000077500000000000000000000000001413160260300127675ustar00rootroot00000000000000libzpc-1.0.0/.gitignore000066400000000000000000000000361413160260300147560ustar00rootroot00000000000000doc/html/ doc/latex/ .vscode/ libzpc-1.0.0/.indent.pro000066400000000000000000000063411413160260300150540ustar00rootroot00000000000000// *** libzpc indent options *** // // To use the indent tool with the specified options, copy this file to your // home directory or set the INDENT_PROFILE environment variable's value to // name this file e.g., do // // export INDENT_PROFILE=`pwd`/.indent.pro // // from the root of the source tree. // // See indent(1). // *** INVOKIND INDENT *** //--standard-output //--ignore-profile // *** COMMON STYLES *** // We use none of them. //--gnu-style //--k-and-r-style //--original //--linux // *** BLANK LINES *** //--blank-lines-after-declarations --no-blank-lines-after-declarations --blank-lines-after-procedures //--no-blank-lines-after-procedures // Puts blank line before header. //--blank-lines-before-block-comments --no-blank-lines-before-block-comments --swallow-optional-blank-lines //--leave-optional-blank-lines // *** COMMENTS *** // Set in BLANK LINES section. //--blank-lines-before-block-comments //--no-blank-lines-before-block-comments --format-all-comments //--dont-format-comments // Puts a trailing space after /* //--format-first-column-comments --dont-format-first-column-comments --comment-line-length80 //--fix-nested-comments --line-comments-indentation0 --comment-indentation0 --declaration-comment-column0 --else-endif-column0 --left-justify-declarations //--dont-left-justify-declarations //--dont-tab-align-comments //--comment-delimiters-on-blank-lines --no-comment-delimiters-on-blank-lines --start-left-side-of-comments //--dont-star-comments // *** STATEMENTS *** --braces-on-if-line //--braces-after-if-line //--brace-indent0 --cuddle-else //--dont-cuddle-else --cuddle-do-while //--dont-cuddle-do-while //--single-line-conditionals --case-indentation0 --case-brace-indentation0 //--space-special-semicolon --dont-space-special-semicolon //--space-after-procedure-calls --no-space-after-function-call-names //--space-after-cast --no-space-after-casts //--blank-before-sizeof --space-after-for //--no-space-after-for --space-after-if //--no-space-after-if --space-after-while //--no-space-after-while //--space-after-parentheses --no-space-after-parentheses --struct-brace-indentation0 // *** DECLARATIONS *** --declaration-indentation0 //--blank-lines-after-commas --no-blank-lines-after-commas //--break-function-decl-args --dont-break-function-decl-args //--break-function-decl-args-end --dont-break-function-decl-args-end --procnames-start-lines //--dont-break-procedure-type --braces-on-struct-decl-line //--braces-after-struct-decl-line //--braces-on-func-def-line --braces-after-func-def-line //--spaces-around-initializers // *** IDENTATION *** --use-tabs //--no-tabs --indent-level8 --continuation-indentation4 //--continue-at-parentheses --dont-line-up-parentheses --paren-indentation0 --tab-size8 --align-with-spaces --parameter-indentation4 //--no-parameter-indentation // Overridden by --preprocessor-indentationn. //--leave-preprocessor-space //-nps --preprocessor-indentation1 --indent-label0 // *** BREAKING LONG LINES *** --line-length80 --break-before-boolean-operator //--break-after-boolean-operator //--honour-newlines --ignore-newlines //--gettext-strings --no-gettext-strings // *** MISCELLANEOUS OPTIONS *** //--verbose --no-verbosity //--preserve-mtime libzpc-1.0.0/.travis.yml000066400000000000000000000006511413160260300151020ustar00rootroot00000000000000arch: s390x os: linux dist: bionic language: cpp sudo: required env: | CFLAGS="-O3 -Wextra -Wextra -Werror" CXXFLAGS="-O3 -Wextra -Wextra -Werror" compiler: - gcc - clang before_install: - sudo apt-get update -qq - sudo apt-get install cmake libjson-c-dev script: - mkdir build && cd build - cmake -DBUILD_TEST=ON .. - make libzpc-1.0.0/CHANGES.md000066400000000000000000000006411413160260300143620ustar00rootroot00000000000000Changelog {#changes} === **Version 1.0** - Implements an error API : `zpc/error.h`. - Implements an AES-KEY API : `zpc/aes_key.h`. - Implements an AES-GCM API : `zpc/aes_gcm.h`. - Implements an AES-CCM API : `zpc/aes_ccm.h`. - Implements an AES-XTS API : `zpc/aes_xts.h`. - Implements an AES-CBC API : `zpc/aes_cbc.h`. - Implements an AES-ECB API : `zpc/aes_ecb.h`. - Implements an AES-CMAC API : `zpc/aes_cmac.h`. libzpc-1.0.0/CMakeLists.txt000066400000000000000000000231161413160260300155320ustar00rootroot00000000000000########################################################### set(ZPC_NAME "libzpc" ) set(ZPC_DESCRIPTION "IBM Z Protected-key Crypto library") set(ZPC_VERSION_MAJOR 1 ) set(ZPC_VERSION_MINOR 0 ) set(ZPC_VERSION_PATCH 0 ) ########################################################### cmake_minimum_required( VERSION 3.10 ) # Honor symbol visibility properties for all target types. # https://cmake.org/cmake/help/git-stage/policy/CMP0063.html if(POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() set(CMAKE_C_STANDARD 99) set(CMAKE_C_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD_REQUIRED ON) project(${ZPC_NAME} VERSION ${ZPC_VERSION_MAJOR}.${ZPC_VERSION_MINOR}.${ZPC_VERSION_PATCH} DESCRIPTION ${ZPC_DESCRIPTION} LANGUAGES CXX C ASM ) set(ZPC_HEADERS include/zpc/error.h include/zpc/aes_key.h include/zpc/aes_gcm.h include/zpc/aes_ccm.h include/zpc/aes_xts.h include/zpc/aes_cbc.h include/zpc/aes_ecb.h include/zpc/aes_cmac.h ) set(ZPC_SOURCES src/globals.c src/error.c src/misc.c src/misc_asm.S src/aes_key.c src/aes_ecb.c src/aes_cbc.c src/aes_xts.c src/aes_cmac.c src/aes_ccm.c src/aes_gcm.c src/zkey/utils.c src/zkey/pkey.c src/zkey/cca.c src/zkey/ep11.c src/zkey/lib/util_base.c src/zkey/lib/util_file.c src/zkey/lib/util_libc.c src/zkey/lib/util_panic.c src/zkey/lib/util_path.c src/zkey/lib/util_prg.c ) find_library(PTHREAD REQUIRED NAMES pthread ) find_library(JSON_C REQUIRED NAMES json-c ) add_definitions( -D_GNU_SOURCE ) set(ZPC_LIBS ${PTHREAD} ${CMAKE_DL_LIBS} ) add_library(zpc ${ZPC_SOURCES}) set_target_properties(zpc PROPERTIES VERSION ${ZPC_VERSION_MAJOR}.${ZPC_VERSION_MINOR}.${ZPC_VERSION_PATCH} SOVERSION ${ZPC_VERSION_MAJOR} PUBLIC_HEADER "${ZPC_HEADERS}" C_VISIBILITY_PRESET hidden CXX_VISIBILITY_PRESET hidden LINK_FLAGS "-Wl,--version-script=${CMAKE_SOURCE_DIR}/libzpc.map" ) target_include_directories(zpc PRIVATE include src src/zkey) target_link_libraries(zpc ${ZPC_LIBS}) target_compile_definitions( zpc PRIVATE ZPC_VERSION_MAJOR=${ZPC_VERSION_MAJOR} ZPC_VERSION_MINOR=${ZPC_VERSION_MINOR} ZPC_VERSION_PATCH=${ZPC_VERSION_PATCH} ) configure_file(libzpc.pc.in libzpc.pc @ONLY) include(GNUInstallDirs) install( TARGETS zpc LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/zpc/ ) install( FILES ${CMAKE_BINARY_DIR}/libzpc.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig ) option(BUILD_TEST OFF) if (BUILD_TEST) enable_testing() set(GTEST_URL https://github.com/google/googletest/archive/refs/tags/release-1.11.0.zip ) set(GTEST_SHA256 353571c2440176ded91c2de6d6cd88ddd41401d14692ec1f99e35d013feda55a ) set(WYCHEPROOF_GIT https://github.com/google/wycheproof.git ) set(WYCHEPROOF_TAG 2196000605e45d91097147c9c71f26b72af58003 ) set(NIST_AES_URL https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/aesmmt.zip ) set(NIST_AES_SHA256 12d1616f7a713e807714055973f04efc402f46a14e3d81869717c7ace4ecbaf0 ) set(NIST_AES_GCM_URL https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/gcmtestvectors.zip ) set(NIST_AES_GCM_SHA256 f9fc479e134cde2980b3bb7cddbcb567b2cd96fd753835243ed067699f26a023 ) set(NIST_AES_CCM_URL https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip ) set(NIST_AES_CCM_SHA256 0e3c96761bd8f1a0b4dfe666146c32f7d367a49968375ff091b8da9ecaa673aa ) set(NIST_AES_CCM_URL https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/ccmtestvectors.zip ) set(NIST_AES_CCM_SHA256 0e3c96761bd8f1a0b4dfe666146c32f7d367a49968375ff091b8da9ecaa673aa ) set(NIST_AES_CMAC_URL https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/mac/cmactestvectors.zip ) set(NIST_AES_CMAC_SHA256 bdda4edade394c9a2ae74d9cd0921caa120c911a5e735e37abf39d0d5f062be1 ) set(NIST_AES_XTS_URL https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/aes/XTSTestVectors.zip ) set(NIST_AES_XTS_SHA256 67bb04b018182f65530596786e7783f817d2e56509bf3b1f066609b8e3e29c36 ) include(ExternalProject) ExternalProject_Add(nist_aes URL ${NIST_AES_URL} URL_HASH SHA256=${NIST_AES_SHA256} PREFIX ${CMAKE_BINARY_DIR}/nist_aes CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) ExternalProject_Get_Property(nist_aes SOURCE_DIR) set(NIST_AES_SOURCE_DIR ${SOURCE_DIR} ) add_custom_command( OUTPUT nist_aes_ecb.json COMMAND ${CMAKE_SOURCE_DIR}/misc/nist2json_aes_ecb.pl ${NIST_AES_SOURCE_DIR}/ECBMMT* WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS nist_aes ) add_custom_target(nist_aes_ecb_json ALL DEPENDS nist_aes_ecb.json) add_custom_command( OUTPUT nist_aes_cbc.json COMMAND ${CMAKE_SOURCE_DIR}/misc/nist2json_aes_cbc.pl ${NIST_AES_SOURCE_DIR}/CBCMMT* WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS nist_aes ) add_custom_target(nist_aes_cbc_json ALL DEPENDS nist_aes_cbc.json) ExternalProject_Add(nist_aes_xts URL ${NIST_AES_XTS_URL} URL_HASH SHA256=${NIST_AES_XTS_SHA256} PREFIX ${CMAKE_BINARY_DIR}/nist_aes_xts CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) ExternalProject_Get_Property(nist_aes_xts SOURCE_DIR) set(NIST_AES_XTS_SOURCE_DIR ${SOURCE_DIR} ) add_custom_command( OUTPUT nist_aes_xts.json COMMAND ${CMAKE_SOURCE_DIR}/misc/nist2json_aes_xts.pl ${NIST_AES_XTS_SOURCE_DIR}/'format tweak value input - 128 hex str'/* WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS nist_aes_xts ) add_custom_target(nist_aes_xts_json ALL DEPENDS nist_aes_xts.json) ExternalProject_Add(nist_aes_gcm URL ${NIST_AES_GCM_URL} URL_HASH SHA256=${NIST_AES_GCM_SHA256} PREFIX ${CMAKE_BINARY_DIR}/nist_aes_gcm CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) ExternalProject_Get_Property(nist_aes_gcm SOURCE_DIR) set(NIST_AES_GCM_SOURCE_DIR ${SOURCE_DIR} ) add_custom_command( OUTPUT nist_aes_gcm.json COMMAND ${CMAKE_SOURCE_DIR}/misc/nist2json_aes_gcm.pl ${NIST_AES_GCM_SOURCE_DIR}/* WORKING_DIRECTORY ${CMAKE_BINARY_DIR} DEPENDS nist_aes_gcm ) add_custom_target(nist_aes_gcm_json ALL DEPENDS nist_aes_gcm.json) ExternalProject_Add(nist_aes_ccm URL ${NIST_AES_CCM_URL} URL_HASH SHA256=${NIST_AES_CCM_SHA256} PREFIX ${CMAKE_BINARY_DIR}/nist_aes_ccm CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) ExternalProject_Get_Property(nist_aes_ccm SOURCE_DIR) set(NIST_AES_CCM_SOURCE_DIR ${SOURCE_DIR} ) ExternalProject_Add(nist_aes_cmac URL ${NIST_AES_CMAC_URL} URL_HASH SHA256=${NIST_AES_CMAC_SHA256} PREFIX ${CMAKE_BINARY_DIR}/nist_aes_cmac CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) ExternalProject_Get_Property(nist_aes_cmac SOURCE_DIR) set(NIST_AES_CMAC_SOURCE_DIR ${SOURCE_DIR} ) ExternalProject_Add(wycheproof GIT_REPOSITORY ${WYCHEPROOF_GIT} GIT_TAG ${WYCHEPROOF_TAG} PREFIX ${CMAKE_BINARY_DIR}/wycheproof CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" TEST_COMMAND "" ) ExternalProject_Add(gtest URL ${GTEST_URL} URL_HASH SHA256=${GTEST_SHA256} PREFIX ${CMAKE_BINARY_DIR}/gtest INSTALL_COMMAND "" TEST_COMMAND "" ) ExternalProject_Get_Property(gtest SOURCE_DIR BINARY_DIR) set(GTEST_INCLUDE_DIR ${SOURCE_DIR}/googletest/include ) set(GTEST_LIB_DIR ${BINARY_DIR}/lib ) set(ZPC_TEST_LIBS ${GTEST_LIB_DIR}/libgtest_main.a ${GTEST_LIB_DIR}/libgtest.a ${PTHREAD} ${JSON_C} zpc ) set(ZPC_TEST_SOURCES test/testlib.cc test/b_platform.c test/b_headers.c test/b_error.c test/b_aes_key.c test/b_aes_ecb.c test/b_aes_cbc.c test/b_aes_xts.c test/b_aes_cmac.c test/b_aes_ccm.c test/b_aes_gcm.c test/t_system.cc test/t_testlib.cc test/t_environment.cc test/t_error.cc test/t_aes_key.cc test/t_aes_ecb.cc test/t_aes_cbc.cc test/t_aes_cmac.cc test/t_aes_xts.cc test/t_aes_ccm.cc test/t_aes_gcm.cc ) add_executable(runtest ${ZPC_TEST_SOURCES}) add_dependencies(runtest gtest) target_link_libraries(runtest ${ZPC_TEST_LIBS}) target_include_directories(runtest PRIVATE include src ${GTEST_INCLUDE_DIR}) include(GoogleTest) gtest_discover_tests(runtest) endif () ########################################################### # doc option(BUILD_DOC OFF) if (BUILD_DOC) find_package(Doxygen) if (DOXYGEN_FOUND) set(DOXYFILE ${CMAKE_SOURCE_DIR}/doc/Doxyfile ) add_custom_target(doc ALL COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) endif () endif () libzpc-1.0.0/CONTRIBUTING.md000066400000000000000000000027341413160260300152260ustar00rootroot00000000000000Contributing {#contrib} === You can contribute to `libzpc` by submitting issues (feature requests, bug reports) or pull requests (code contributions) to the GitHub repository. Bug reports --- When filing a bug report, please include all relevant information. In all cases include the `libzpc` version, operating system and kernel version used. Additionally, if it is a build error, include the toolchain version used. If it is a runtime error, include the crypto adapter config and processor model used. Ideally, detailed steps on how to reproduce the issue would be included. Code contributions --- All code contributions are reviewed by the `libzpc` maintainers who reverve the right to accept or reject a pull request. Please state clearly if your pull request changes the `libzpc` API or ABI, and if so, whether the changes are backward compatible. If your pull request resolves an issue, please put a `"Fixes #"` line in the commit message. Ideally, the pull request would add a corresponding regression test. If your pull request adds a new feature, please add a corresponding unit test. The code base is formatted using the `indent` tool with the options specified in the enclosed `.indent.pro` file. All code contributions must not violate this coding style. When formatting `libzpc` code, you can use `indent` with the prescribed options by copying the file to your home directory or by setting the `INDENT_PROFILE` environment variable's value to name the file. libzpc-1.0.0/LICENSE000066400000000000000000000020451413160260300137750ustar00rootroot00000000000000Copyright IBM Corp. 2001, 2017, 2020 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. libzpc-1.0.0/README.md000066400000000000000000000104141413160260300142460ustar00rootroot00000000000000Introduction {#index} === The IBM Z Protected-key Crypto library `libzpc` is an open-source library targeting the 64-bit Linux on IBM Z (s390x) platform. It provides interfaces for cryptographic primitives. The underlying implementations make use of z/Architecture's extensive performance-boosting hardware support and its *protected-key* feature which ensures that key material is never present in main memory at any time. The `libzpc` source is hosted on [GitHub](https://github.com/opencryptoki/libzpc). Supported crypto --- Encryption (Cipher): AES-128-ECB, AES-192-ECB, AES-256-ECB AES-128-CBC, AES-192-CBC, AES-256-CBC AES-128-XTS, AES-256-XTS Message authentication (MAC): AES-128-CMAC, AES-192-CMAC, AES-256-CMAC Authenticated Encryption (AEAD): AES-128-CCM, AES-192-CCM, AES-256-CCM AES-128-GCM, AES-192-GCM, AES-256-GCM Building --- Basic prerequisites for building the library only: - Linux kernel >= 5.7 - C99 compiler (clang, gcc) - libpthread - cmake >= 3.10 - make Additional prerequisites for building the test program: - C++11 compiler (clang, g++) - libjson-c devel package >= 0.13 - internet connection Additional prerequisites for building the html and latex doc: - doxygen >= 1.8.17 - latex, bibtex Building `libzpc`: mkdir build && cd build cmake .. make The following options can be passed to `cmake`: - `-DCMAKE_INSTALL_PREFIX=` : Change the install prefix from `/usr/local/` to ``. - `-DCMAKE_BUILD_TYPE=` : Choose predefined build options. The choices for `` are `Debug`, `Release`, `RelWithDebInfo`, and `MinSizeRel`. - `-DBUILD_SHARED_LIBS=ON` : Build a shared object (instead of an archive). - `-DBUILD_TEST=ON` : Build the test program. - `-DBUILD_DOC=ON` : Build the html and latex doc. See `cmake(1)`. Custom compile options can also be passed to `cmake` via the `CFLAGS` and `CXXFLAGS` environment variables in the usual way. Testing --- To run all tests, do ./runtest from the build directory. The following environment variables can be passed to `./runtest`: - `ZPC_TEST_AES_KEY_TYPE=` : The choices for `` are `ZPC_AES_KEY_TYPE_CCA_DATA`, `ZPC_AES_KEY_TYPE_CCA_CIPHER` and `ZPC_AES_KEY_TYPE_EP11`. AES tests are skipped if this variable is unset or its value is invalid. - `ZPC_TEST_AES_KEY_SIZE=` : The choices for `` are `128`, `192` and `256`. AES tests are skipped if this variable is unset or its value is invalid. - `ZPC_TEST_AES_KEY_FLAGS=` : `` is a 4 byte unsigned integer value that specifies the key's flags. `` defaults to `0` if this variable is unset or its value is invalid. - `ZPC_TEST_AES_KEY_MKVP=` : Test the APQNs that match `` and key type. - `ZPC_TEST_AES_KEY_APQNS=` : Test the ``. See ./runtest -h for help. Installing --- To install the shared library, do sudo make install sudo ldconfig Configuration --- To do something useful with `libzpc`, at least one CryptoExpress (CEX) HSM with a master key configuration is required. The device drivers for CEX adapters are documented in chapters 54 and 57 of the kernel 5.7 version of [Linux on Z and LinuxONE - Device Drivers, Features, and Commands](https://www.ibm.com/support/knowledgecenter/linuxonibm/liaaf/lnz_r_dd.html). Here are instructions on [how to set an AES master key](https://www.ibm.com/support/knowledgecenter/linuxonibm/liaaf/lnz_r_dtke.html) for a CEX adapter in CCA coprocessor mode using the Trusted Key Entry (TKE). Programming --- Applications include the `` header files corresponding to the APIs required and link with `-lzp`. With the exeption of `zpc_error_string`, all `libzpc` function return either no value or an integer which is either zero (in case of success) of a non-zero error code (in case of failure). In case of multiple errors, the `libzpc` API leaves the precedence of error codes undefined. Therefore, applications should always check for a non-zero return value before handling specific errors e.g.: rc = zpc_foo(); if (rc) { /* Handle specific error codes. */ fprintf(stderr, "Error: %d (%s).\n", rc, zpc_error_string(rc)); } Debugging --- Setting the environment variable `ZPC_DEBUG=1` will have the library print debug information to `stderr`. License --- See `LICENSE` file. libzpc-1.0.0/doc/000077500000000000000000000000001413160260300135345ustar00rootroot00000000000000libzpc-1.0.0/doc/DOC.md000066400000000000000000000002211413160260300144560ustar00rootroot00000000000000doc === UMLet --- The `.uxf` (UMLet diagram format) files can be edited with the UMLet tool and exported to other format like `.eps` or `.jpg`. libzpc-1.0.0/doc/Doxyfile000066400000000000000000000321751413160260300152520ustar00rootroot00000000000000# Doxyfile 1.8.17 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = libzpc PROJECT_NUMBER = 1.0 PROJECT_BRIEF = "IBM Z Protected-key Crypto library" PROJECT_LOGO = OUTPUT_DIRECTORY = doc CREATE_SUBDIRS = NO ALLOW_UNICODE_NAMES = NO OUTPUT_LANGUAGE = English OUTPUT_TEXT_DIRECTION = None BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = include STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO JAVADOC_BANNER = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 4 ALIASES = TCL_SUBST = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO OPTIMIZE_OUTPUT_SLICE = NO EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES TOC_INCLUDE_HEADINGS = 5 AUTOLINK_SUPPORT = YES BUILTIN_STL_SUPPORT = NO CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES DISTRIBUTE_GROUP_DOC = NO GROUP_NESTED_COMPOUNDS = NO SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = NO LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = NO EXTRACT_PRIVATE = NO EXTRACT_PRIV_VIRTUAL = NO EXTRACT_PACKAGE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = NO EXTRACT_LOCAL_METHODS = NO EXTRACT_ANON_NSPACES = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO HIDE_SCOPE_NAMES = YES HIDE_COMPOUND_REFERENCE= NO SHOW_INCLUDE_FILES = NO SHOW_GROUPED_MEMB_INC = NO FORCE_LOCAL_INCLUDES = NO INLINE_INFO = YES SORT_MEMBER_DOCS = NO SORT_BRIEF_DOCS = NO SORT_MEMBERS_CTORS_1ST = NO SORT_GROUP_NAMES = NO SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO GENERATE_TODOLIST = NO GENERATE_TESTLIST = NO GENERATE_BUGLIST = NO GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_FILES = YES SHOW_NAMESPACES = YES FILE_VERSION_FILTER = LAYOUT_FILE = CITE_BIB_FILES = doc/references.bib #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = YES WARN_AS_ERROR = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- INPUT = include/zpc \ README.md \ CHANGES.md \ CONTRIBUTING.md INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.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 \ *.doc \ *.txt \ *.py \ *.pyw \ *.f90 \ *.f95 \ *.f03 \ *.f08 \ *.f \ *.for \ *.tcl \ *.vhd \ *.vhdl \ *.ucf \ *.qsf \ *.ice RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = doc/ INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES SOURCE_TOOLTIPS = YES USE_HTAGS = NO VERBATIM_HEADERS = YES CLANG_ASSISTED_PARSING = NO CLANG_OPTIONS = CLANG_DATABASE_PATH = #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_EXTRA_STYLESHEET = HTML_EXTRA_FILES = HTML_COLORSTYLE_HUE = 220 HTML_COLORSTYLE_SAT = 100 HTML_COLORSTYLE_GAMMA = 80 HTML_TIMESTAMP = NO HTML_DYNAMIC_MENUS = YES HTML_DYNAMIC_SECTIONS = NO HTML_INDEX_NUM_ENTRIES = 100 GENERATE_DOCSET = NO DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project DOCSET_PUBLISHER_ID = org.doxygen.Publisher DOCSET_PUBLISHER_NAME = Publisher GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO CHM_INDEX_ENCODING = BINARY_TOC = NO TOC_EXPAND = NO GENERATE_QHP = NO QCH_FILE = QHP_NAMESPACE = org.doxygen.Project QHP_VIRTUAL_FOLDER = doc QHP_CUST_FILTER_NAME = QHP_CUST_FILTER_ATTRS = QHP_SECT_FILTER_ATTRS = QHG_LOCATION = GENERATE_ECLIPSEHELP = NO ECLIPSE_DOC_ID = org.doxygen.Project DISABLE_INDEX = NO GENERATE_TREEVIEW = NO ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 EXT_LINKS_IN_WINDOW = NO FORMULA_FONTSIZE = 10 FORMULA_TRANSPARENT = YES FORMULA_MACROFILE = USE_MATHJAX = NO MATHJAX_FORMAT = HTML-CSS MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/ MATHJAX_EXTENSIONS = MATHJAX_CODEFILE = SEARCHENGINE = YES SERVER_BASED_SEARCH = NO EXTERNAL_SEARCH = NO SEARCHENGINE_URL = SEARCHDATA_FILE = searchdata.xml EXTERNAL_SEARCH_ID = EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = YES LATEX_OUTPUT = latex LATEX_CMD_NAME = MAKEINDEX_CMD_NAME = makeindex LATEX_MAKEINDEX_CMD = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4 EXTRA_PACKAGES = LATEX_HEADER = LATEX_FOOTER = LATEX_EXTRA_STYLESHEET = LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES USE_PDFLATEX = YES LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain LATEX_TIMESTAMP = NO LATEX_EMOJI_DIRECTORY = #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = RTF_SOURCE_CODE = NO #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_SUBDIR = MAN_LINKS = NO #--------------------------------------------------------------------------- # Configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_PROGRAMLISTING = YES XML_NS_MEMB_FILE_SCOPE = NO #--------------------------------------------------------------------------- # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook DOCBOOK_PROGRAMLISTING = NO #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # Configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES SEARCH_INCLUDES = NO INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = __attribute__(x)= EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration options related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES EXTERNAL_PAGES = YES #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = NO DIA_PATH = HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO DOT_NUM_THREADS = 0 DOT_FONTNAME = Helvetica DOT_FONTSIZE = 10 DOT_FONTPATH = CLASS_GRAPH = NO COLLABORATION_GRAPH = NO GROUP_GRAPHS = NO UML_LOOK = NO UML_LIMIT_NUM_FIELDS = 10 TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = NO INCLUDED_BY_GRAPH = NO CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = NO DIRECTORY_GRAPH = NO DOT_IMAGE_FORMAT = png INTERACTIVE_SVG = NO DOT_PATH = DOTFILE_DIRS = MSCFILE_DIRS = DIAFILE_DIRS = PLANTUML_JAR_PATH = PLANTUML_CFG_FILE = PLANTUML_INCLUDE_PATH = DOT_GRAPH_MAX_NODES = 50 MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES libzpc-1.0.0/doc/references.bib000066400000000000000000000030701413160260300163330ustar00rootroot00000000000000@misc{POP, title = "{IBM} z/{A}rchitecture {P}rinciples of {O}perations, {SA}22-7832-12", year = "2019", note = "\url{https://publibfp.dhe.ibm.com/epubs/pdf/a227832c.pdf}" } @misc{AES, title = "{NIST} {FIPS} 197 - {A}nnouncing the {ADVANCED} {ENCRYPTION} {STANDARD} ({AES})", year = "2001", note = "\url{https://doi.org/10.6028/NIST.FIPS.197}" } @misc{MODES, title = "{NIST} {SP} 800-38{A} - {R}ecommendation for {B}lock {C}ipher {M}odes of {O}peration: {M}ethods and {T}echniques", year = "2001", note = "\url{https://doi.org/10.6028/NIST.SP.800-38A}" } @misc{CMAC, title = "{NIST} {SP} 800-38{B} - {R}ecommendation for {B}lock {C}ipher {M}odes of {O}peration: The {CMAC} {M}ode for {A}uthentication", year = "2005", note = "\url{https://doi.org/10.6028/NIST.SP.800-38B}" } @misc{CCM, title = "{NIST} {SP} 800-38{C} - {R}ecommendation for {B}lock {C}ipher {M}odes of {O}peration: The {CCM} {M}ode for {A}uthentication and {C}onfidentiality", year = "2004", note = "\url{https://doi.org/10.6028/NIST.SP.800-38C}" } @misc{GCM, title = "{NIST} {SP} 800-38{D} - {R}ecommendation for {B}lock {C}ipher {M}odes of {O}peration: {G}alois/{C}ounter {M}ode ({GCM}) and {GMAC}", year = "2007", note = "\url{https://doi.org/10.6028/NIST.SP.800-38D}" } @misc{XTS, title = "{NIST} {SP} 800-38{E} - {R}ecommendation for {B}lock {C}ipher {M}odes of {O}peration: The {XTS}-{AES} {M}ode for {C}onfidentiality on {S}torage {D}evices", year = "2010", note = "\url{https://doi.org/10.6028/NIST.SP.800-38E}" } libzpc-1.0.0/include/000077500000000000000000000000001413160260300144125ustar00rootroot00000000000000libzpc-1.0.0/include/zpc/000077500000000000000000000000001413160260300152065ustar00rootroot00000000000000libzpc-1.0.0/include/zpc/aes_cbc.h000066400000000000000000000050211413160260300167340ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_AES_CBC_H # define ZPC_AES_CBC_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/aes_cbc.h * * \brief AES-CBC API * * Encryption API for the Advanced Encryption Standard (AES) * block cipher \cite AES in Cipher Block Chaining (CBC) * mode of operation \cite MODES . */ # include # include struct zpc_aes_cbc; /** * Allocate a new context for an AES-CBC operation. * \param[in,out] ctx AES-CBC context * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cbc_alloc(struct zpc_aes_cbc **ctx); /** * Set the key to be used in the context of an AES-CBC operation. * \param[in,out] ctx AES-CBC context * \param[in] key AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cbc_set_key(struct zpc_aes_cbc *ctx, struct zpc_aes_key *key); /** * Set the initialization vector to be used in the context * of an AES-CBC operation. * \param[in,out] ctx AES-CBC context * \param[in] iv 16 byte initialization vector * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cbc_set_iv(struct zpc_aes_cbc *ctx, const unsigned char *iv); /** * Do an AES-CBC encryption operation. * \param[in,out] ctx AES-CBC context * \param[out] ct ciphertext * \param[in] pt plaintext * \param[in] ptlen plaintext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cbc_encrypt(struct zpc_aes_cbc *ctx, unsigned char *ct, const unsigned char *pt, size_t ptlen); /** * Do an AES-CBC decryption operation. * \param[in,out] ctx AES-CBC context * \param[out] pt plaintext * \param[in] ct ciphertext * \param[in] ctlen ciphertext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cbc_decrypt(struct zpc_aes_cbc *ctx, unsigned char *pt, const unsigned char *ct, size_t ctlen); /** * Free an AES-CBC context. * \param[in,out] ctx AES-CBC context */ __attribute__((visibility("default"))) void zpc_aes_cbc_free(struct zpc_aes_cbc **ctx); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/include/zpc/aes_ccm.h000066400000000000000000000063441413160260300167600ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_AES_CCM_H # define ZPC_AES_CCM_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/aes_ccm.h * * \brief AES-CCM API * * Authenticated encryption API for the Advanced Encryption Standard (AES) * block cipher \cite AES in Counter with CBC-MAC mode of operation \cite CCM . */ # include # include struct zpc_aes_ccm; /** * Allocate a new context for an AES-CCM operation. * \param[in,out] ctx AES-CCM context * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ccm_alloc(struct zpc_aes_ccm **ctx); /** * Set the key to be used in the context of an AES-CCM operation. * \param[in,out] ctx AES-CCM context * \param[in] key AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ccm_set_key(struct zpc_aes_ccm *ctx, struct zpc_aes_key *key); /** * Set the initialization vector to be used in the context * of an AES-CCM operation. * \param[in,out] ctx AES-CCM context * \param[in] iv 7-13 byte initialization vector * \param[in] ivlen initialization vector length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ccm_set_iv(struct zpc_aes_ccm *ctx, const unsigned char *iv, size_t ivlen); /** * Do an AES-CCM authenticated encryption operation. * \param[in,out] ctx AES-CCM context * \param[out] ct ciphertext * \param[out] mac message authentication code * \param[in] maclen message authentication code length [bytes] * \param[in] aad additional authenticated data * \param[in] aadlen additional authenticated data length [bytes] * \param[in] pt plaintext * \param[in] ptlen plaintext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ccm_encrypt(struct zpc_aes_ccm *ctx, unsigned char *ct, unsigned char *mac, size_t maclen, const unsigned char *aad, size_t aadlen, const unsigned char *pt, size_t ptlen); /** * Do an AES-CCM authenticated decryption operation. * \param[in,out] ctx AES-CCM context * \param[out] pt plaintext * \param[in] mac message authentication code * \param[in] maclen message authentication code length [bytes] * \param[in] aad additional authenticated data * \param[in] aadlen additional authenticated data length [bytes] * \param[in] ct ciphertext * \param[in] ctlen ciphertext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ccm_decrypt(struct zpc_aes_ccm *ctx, unsigned char *pt, const unsigned char *mac, size_t maclen, const unsigned char *aad, size_t aadlen, const unsigned char *ct, size_t ctlen); /** * Free an AES-CCM context. * \param[in,out] ctx AES-CCM context */ __attribute__((visibility("default"))) void zpc_aes_ccm_free(struct zpc_aes_ccm **ctx); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/include/zpc/aes_cmac.h000066400000000000000000000046241413160260300171200ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_AES_CMAC_H # define ZPC_AES_CMAC_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/aes_cmac.h * * \brief AES-CMAC API * * Message authentication API for the Cipher-based Message Authentication * Code (CMAC) \cite CMAC based on the Advanced Encryption Standard (AES) * block cipher \cite AES . */ # include # include struct zpc_aes_cmac; /** * Allocate a new context for an AES-CMAC operation. * \param[in,out] ctx AES-CMAC context * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cmac_alloc(struct zpc_aes_cmac **ctx); /** * Set the key to be used in the context of an AES-CMAC operation. * \param[in,out] ctx AES-CMAC context * \param[in] key AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cmac_set_key(struct zpc_aes_cmac *ctx, struct zpc_aes_key *key); /** * Do an AES-CMAC signing operation. * \param[in,out] ctx AES-CMAC context * \param[out] mac message authentication code * \param[in] maclen message authentication code length [bytes] * \param[in] msg message * \param[in] msglen message length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cmac_sign(struct zpc_aes_cmac *ctx, unsigned char *mac, size_t maclen, const unsigned char *msg, size_t msglen); /** * Do an AES-CMAC verify operation. * \param[in,out] ctx AES-CMAC context * \param[in] mac message authentication code * \param[in] maclen message authentication code length [bytes] * \param[in] msg message * \param[in] msglen message length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_cmac_verify(struct zpc_aes_cmac *ctx, const unsigned char *mac, size_t maclen, const unsigned char *msg, size_t msglen); /** * Free an AES-CMAC context. * \param[in,out] ctx AES-CMAC context */ __attribute__((visibility("default"))) void zpc_aes_cmac_free(struct zpc_aes_cmac **ctx); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/include/zpc/aes_ecb.h000066400000000000000000000042441413160260300167440ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_AES_ECB_H # define ZPC_AES_ECB_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/aes_ecb.h * * \brief AES-ECB API * * Encryption API for the Advanced Encryption Standard (AES) * block cipher \cite AES in Electronic Code Book (ECB) * mode of operation \cite MODES . */ # include # include struct zpc_aes_ecb; /** * Allocate a new context for an AES-ECB operation. * \param[in,out] ctx AES-ECB context * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ecb_alloc(struct zpc_aes_ecb **ctx); /** * Set the key to be used in the context of an AES-ECB operation. * \param[in,out] ctx AES-ECB context * \param[in] key AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ecb_set_key(struct zpc_aes_ecb *ctx, struct zpc_aes_key *key); /** * Do an AES-ECB encryption operation. * \param[in,out] ctx AES-ECB context * \param[out] ct ciphertext * \param[in] pt plaintext * \param[in] ptlen plaintext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ecb_encrypt(struct zpc_aes_ecb *ctx, unsigned char *ct, const unsigned char *pt, size_t ptlen); /** * Do an AES-ECB decryption operation. * \param[in,out] ctx AES-ECB context * \param[out] pt plaintext * \param[in] ct ciphertext * \param[in] ctlen ciphertext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_ecb_decrypt(struct zpc_aes_ecb *ctx, unsigned char *pt, const unsigned char *ct, size_t ctlen); /** * Free an AES-ECB context. * \param[in,out] ctx AES-ECB context */ __attribute__((visibility("default"))) void zpc_aes_ecb_free(struct zpc_aes_ecb **ctx); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/include/zpc/aes_gcm.h000066400000000000000000000063301413160260300167570ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_AES_GCM_H # define ZPC_AES_GCM_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/aes_gcm.h * * \brief AES-GCM API * * Authenticated encryption API for the Advanced Encryption Standard (AES) * block cipher \cite AES in Galois/Counter Mode mode of operation \cite GCM . */ # include # include struct zpc_aes_gcm; /** * Allocate a new context for an AES-GCM operation. * \param[in,out] ctx AES-GCM context * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_gcm_alloc(struct zpc_aes_gcm **ctx); /** * Set the key to be used in the context of an AES-GCM operation. * \param[in,out] ctx AES-GCM context * \param[in] key AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_gcm_set_key(struct zpc_aes_gcm *ctx, struct zpc_aes_key *key); /** * Set the initialization vector to be used in the context * of an AES-GCM operation. * \param[in,out] ctx AES-GCM context * \param[in] iv initialization vector * \param[in] ivlen initialization vector length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_gcm_set_iv(struct zpc_aes_gcm *ctx, const unsigned char *iv, size_t ivlen); /** * Do an AES-GCM authenticated encryption operation. * \param[in,out] ctx AES-GCM context * \param[out] ct ciphertext * \param[out] mac message authentication code * \param[in] maclen message authentication code length [bytes] * \param[in] aad additional authenticated data * \param[in] aadlen additional authenticated data length [bytes] * \param[in] pt plaintext * \param[in] ptlen plaintext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_gcm_encrypt(struct zpc_aes_gcm *ctx, unsigned char *ct, unsigned char *mac, size_t maclen, const unsigned char *aad, size_t aadlen, const unsigned char *pt, size_t ptlen); /** * Do an AES-GCM authenticated decryption operation. * \param[in,out] ctx AES-GCM context * \param[out] pt plaintext * \param[in] mac message authentication code * \param[in] maclen message authentication code length [bytes] * \param[in] aad additional authenticated data * \param[in] aadlen additional authenticated data length [bytes] * \param[in] ct ciphertext * \param[in] ctlen ciphertext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_gcm_decrypt(struct zpc_aes_gcm *ctx, unsigned char *pt, const unsigned char *mac, size_t maclen, const unsigned char *aad, size_t aadlen, const unsigned char *ct, size_t ctlen); /** * Free an AES-CCM context. * \param[in,out] ctx AES-GCM context */ __attribute__((visibility("default"))) void zpc_aes_gcm_free(struct zpc_aes_gcm **ctx); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/include/zpc/aes_key.h000066400000000000000000000104431413160260300170010ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_AES_KEY_H # define ZPC_AES_KEY_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/aes_key.h * \brief AES key API. * * Manage advanced Encryption Standard (AES) block cipher * \cite AES keys. */ # include # define ZPC_AES_KEY_TYPE_CCA_DATA 1 # define ZPC_AES_KEY_TYPE_CCA_CIPHER 2 # define ZPC_AES_KEY_TYPE_EP11 3 # define ZPC_AES_KEY_REENCIPHER_OLD_TO_CURRENT 1 # define ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW 2 struct zpc_aes_key; /** * Allocate a new AES key object with reference count 1. * \param[in,out] key AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_alloc(struct zpc_aes_key **key); /** * Set the AES key size. * \param[in,out] key AES key * \param[in] size 128, 192 or 256 bit key size * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_set_size(struct zpc_aes_key *key, int size); /** * Set the AES key type. * \param[in,out] key AES key * \param[in] type ZPC_AES_KEY_TYPE_CCA_DATA, ZPC_AES_KEY_TYPE_CCA_CIPHER * or ZPC_AES_KEY_TYPE_EP11 * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_set_type(struct zpc_aes_key *key, int type); /** * Set the AES key flags. * \param[in,out] key AES key * \param[in] flags key flags * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_set_flags(struct zpc_aes_key *key, unsigned int flags); /** * Set the AES key Master Key Verification Pattern. * \param[in,out] key AES key * \param[in] mkvp master key verification pattern * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_set_mkvp(struct zpc_aes_key *key, const char *mkvp); /** * Set the AES key APQNs * \param[in,out] key AES key * \param[in] apqns NULL-terminated APQN list * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_set_apqns(struct zpc_aes_key *key, const char *apqns[]); /** * Import an AES secure-key. * \param[in,out] key AES key * \param[in] seckey AES secure-key * \param[in] seckeylen AES key secure-length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_import(struct zpc_aes_key *key, const unsigned char *seckey, size_t seckeylen); /** * Import an AES clear-key. * \param[in,out] key AES key * \param[in] clearkey AES clear-key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_import_clear(struct zpc_aes_key *key, const unsigned char *clrkey); /** * Export an AES secure-key. * \param[in,out] key AES key * \param[out] seckey AES secure-key * \param[in,out] seckeylen secure AES secure-key length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_export(struct zpc_aes_key *key, unsigned char *seckey, size_t *seckeylen); /** * Generate an AES secure-key. * \param[in,out] key AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_generate(struct zpc_aes_key *key); /** * Reencipher an AES secure-key. * \param[in,out] key AES key * \param[in] reenc ZPC_AES_KEY_REENCIPHER_OLD_TO_CURRENT * or ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_key_reencipher(struct zpc_aes_key *key, int reenc); /** * Decrease the reference count of an AES key object * and free it the count reaches 0. * \param[in,out] key AES key */ __attribute__((visibility("default"))) void zpc_aes_key_free(struct zpc_aes_key **key); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/include/zpc/aes_xts.h000066400000000000000000000051721413160260300170320ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_AES_XTS_H # define ZPC_AES_XTS_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/aes_xts.h * * \brief AES-XTS API * * Encryption API for the Advanced Encryption Standard (AES) * block cipher \cite AES in XEX-based Tweaked-codebook mode with * ciphertext Stealing (XTS) mode of operation \cite XTS . */ # include # include struct zpc_aes_xts; /** * Allocate a new context for an AES-XTS operation. * \param[in,out] ctx AES-XTS context * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_xts_alloc(struct zpc_aes_xts **ctx); /** * Set the key to be used in the context of an AES-XTS operation. * \param[in,out] ctx AES-XTS context * \param[in] key1 first AES key * \param[in] key2 second AES key * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_xts_set_key(struct zpc_aes_xts *ctx, struct zpc_aes_key *key1, struct zpc_aes_key *key2); /** * Set the initialization vector to be used in the context * of an AES-XTS operation. * \param[in,out] ctx AES-XTS context * \param[in] iv 16 byte initialization vector * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_xts_set_iv(struct zpc_aes_xts *ctx, const unsigned char *iv); /** * Do an AES-XTS encryption operation. * \param[in,out] ctx AES-XTS context * \param[out] ct ciphertext * \param[in] pt plaintext * \param[in] ptlen plaintext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_xts_encrypt(struct zpc_aes_xts *ctx, unsigned char *ct, const unsigned char *pt, size_t ptlen); /** * Do an AES-XTS decryption operation. * \param[in,out] ctx AES-XTS context * \param[out] pt plaintext * \param[in] ct ciphertext * \param[in] ctlen ciphertext length [bytes] * \return 0 on success. Otherwise, a non-zero error code is returned. */ __attribute__((visibility("default"))) int zpc_aes_xts_decrypt(struct zpc_aes_xts *ctx, unsigned char *pt, const unsigned char *ct, size_t ctlen); /** * Free an AES-XTS context. * \param[in,out] ctx AES-XTS context */ __attribute__((visibility("default"))) void zpc_aes_xts_free(struct zpc_aes_xts **ctx); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/include/zpc/error.h000066400000000000000000000135151413160260300165150ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef ZPC_ERROR_H # define ZPC_ERROR_H # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif /** * \file zpc/error.h * \brief Error API. */ /** * \def ZPC_ERROR_ARG1NULL * \brief Function argument 1 is NULL. */ # define ZPC_ERROR_ARG1NULL 1 /** * \def ZPC_ERROR_ARG2NULL * \brief Function argument 2 is NULL. */ # define ZPC_ERROR_ARG2NULL 2 /** * \def ZPC_ERROR_ARG3NULL * \brief Function argument 3 is NULL. */ # define ZPC_ERROR_ARG3NULL 3 /** * \def ZPC_ERROR_ARG4NULL * \brief Function argument 4 is NULL. */ # define ZPC_ERROR_ARG4NULL 4 /** * \def ZPC_ERROR_ARG5NULL * \brief Function argument 5 is NULL. */ # define ZPC_ERROR_ARG5NULL 5 /** * \def ZPC_ERROR_ARG6NULL * \brief Function argument 6 is NULL. */ # define ZPC_ERROR_ARG6NULL 6 /** * \def ZPC_ERROR_ARG7NULL * \brief Function argument 7 is NULL. */ # define ZPC_ERROR_ARG7NULL 7 /** * \def ZPC_ERROR_ARG8NULL * \brief Function argument 8 is NULL. */ # define ZPC_ERROR_ARG8NULL 8 /** * \def ZPC_ERROR_ARG1RANGE * \brief Function argument 1 is out of range. */ # define ZPC_ERROR_ARG1RANGE 9 /** * \def ZPC_ERROR_ARG2RANGE * \brief Function argument 2 is out of range. */ # define ZPC_ERROR_ARG2RANGE 10 /** * \def ZPC_ERROR_ARG3RANGE * \brief Function argument 3 is out of range. */ # define ZPC_ERROR_ARG3RANGE 11 /** * \def ZPC_ERROR_ARG4RANGE * \brief Function argument 4 is out of range. */ # define ZPC_ERROR_ARG4RANGE 12 /** * \def ZPC_ERROR_ARG5RANGE * \brief Function argument 5 is out of range. */ # define ZPC_ERROR_ARG5RANGE 13 /** * \def ZPC_ERROR_ARG6RANGE * \brief Function argument 6 is out of range. */ # define ZPC_ERROR_ARG6RANGE 14 /** * \def ZPC_ERROR_ARG7RANGE * \brief Function argument 7 is out of range. */ # define ZPC_ERROR_ARG7RANGE 15 /** * \def ZPC_ERROR_ARG8RANGE * \brief Function argument 8 is out of range. */ # define ZPC_ERROR_ARG8RANGE 16 /** * \def ZPC_ERROR_MALLOC * \brief Malloc failed. */ # define ZPC_ERROR_MALLOC 17 /** * \def ZPC_ERROR_KEYNOTSET * \brief Key not set. */ # define ZPC_ERROR_KEYNOTSET 18 /** * \def ZPC_ERROR_KEYSIZE * \brief Invalid key size. */ # define ZPC_ERROR_KEYSIZE 19 /** * \def ZPC_ERROR_IVNOTSET * \brief IV not set. */ # define ZPC_ERROR_IVNOTSET 20 /** * \def ZPC_ERROR_IVSIZE * \brief Invalid IV size. */ # define ZPC_ERROR_IVSIZE 21 /** * \def ZPC_ERROR_TAGSIZE * \brief Invalid tag size. */ # define ZPC_ERROR_TAGSIZE 22 /** * \def ZPC_ERROR_TAGMISMATCH * \brief Tag mismatch. */ # define ZPC_ERROR_TAGMISMATCH 23 /** * \def ZPC_ERROR_HWCAPS * \brief Function not supported. */ # define ZPC_ERROR_HWCAPS 24 /** * \def ZPC_ERROR_SMALLOUTBUF * \brief Output buffer too small. */ # define ZPC_ERROR_SMALLOUTBUF 25 /** * \def ZPC_ERROR_APQNSNOTSET * \brief APQNs not set. */ # define ZPC_ERROR_APQNSNOTSET 26 /** * \def ZPC_ERROR_KEYTYPE * \brief Invalid key type. */ # define ZPC_ERROR_KEYTYPE 27 /** * \def ZPC_ERROR_KEYTYPENOTSET * \brief Key type not set. */ # define ZPC_ERROR_KEYTYPENOTSET 28 /** * \def ZPC_ERROR_IOCTLGENSECK2 * \brief PKEY_GENSECK2 ioctl failed. */ # define ZPC_ERROR_IOCTLGENSECK2 29 /** * \def ZPC_ERROR_IOCTLCLR2SECK2 * \brief PKEY_CLR2SECK2 ioctl failed. */ # define ZPC_ERROR_IOCTLCLR2SECK2 30 /** * \def ZPC_ERROR_IOCTLBLOB2PROTK2 * \brief PKEY_BLOB2PROTK2 ioctl failed. */ # define ZPC_ERROR_IOCTLBLOB2PROTK2 31 /** * \def ZPC_ERROR_WKVPMISMATCH * \brief Wrapping key verification pattern mismatch. */ # define ZPC_ERROR_WKVPMISMATCH 32 /** * \def ZPC_ERROR_DEVPKEY * \brief Opening /dev/pkey failed. */ # define ZPC_ERROR_DEVPKEY 33 /** * \def ZPC_ERROR_CLEN * \brief Ciphertext too long. */ # define ZPC_ERROR_CLEN 34 /** * \def ZPC_ERROR_MLEN * \brief Message too long. */ # define ZPC_ERROR_MLEN 35 /** * \def ZPC_ERROR_AADLEN * \brief Additional authenticated data too long. */ # define ZPC_ERROR_AADLEN 36 /** * \def ZPC_ERROR_PARSE * \brief Parse error. */ # define ZPC_ERROR_PARSE 38 /** * \def ZPC_ERROR_APQNNOTFOUND * \brief APQN not found in APQN list. */ # define ZPC_ERROR_APQNNOTFOUND 39 /** * \def ZPC_ERROR_MKVPLEN * \brief MKVP too long. */ # define ZPC_ERROR_MKVPLEN 40 /** * \def ZPC_ERROR_INITLOCK * \brief Initializing a lock failed. */ # define ZPC_ERROR_INITLOCK 42 /** * \def ZPC_ERROR_OBJINUSE * \brief Object is in use. */ # define ZPC_ERROR_OBJINUSE 43 /** * \def ZPC_ERROR_IOCTLAPQNS4KT * \brief PKEY_APQNS4KT ioctl failed. */ # define ZPC_ERROR_IOCTLAPQNS4KT 44 /** * \def ZPC_ERROR_KEYSIZENOTSET * \brief Key-size not set. */ # define ZPC_ERROR_KEYSIZENOTSET 45 /** * \def ZPC_ERROR_IOCTLGENPROTK * \brief PKEY_GENPROTK ioctl failed. */ # define ZPC_ERROR_IOCTLGENPROTK 46 /** * \def ZPC_ERROR_PROTKEYONLY * \brief Protected-key only. */ # define ZPC_ERROR_PROTKEYONLY 47 /** * \def ZPC_ERROR_KEYSEQUAL * \brief Keys are equal. */ # define ZPC_ERROR_KEYSEQUAL 48 /** * \def ZPC_ERROR_NOTSUP * \brief Not supported. */ # define ZPC_ERROR_NOTSUP 49 /** * \fn const char *zpc_error_string(int err) * \brief Map an error code to the corresponding error string. * \param[in] err An error code. * \return A pointer to an error string. */ __attribute__((visibility("default"))) const char *zpc_error_string(int); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif libzpc-1.0.0/libzpc.map000066400000000000000000000020271413160260300147520ustar00rootroot00000000000000ZPC_1.0 { global: zpc_error_string; zpc_aes_key_alloc; zpc_aes_key_set_size; zpc_aes_key_set_type; zpc_aes_key_set_flags; zpc_aes_key_set_mkvp; zpc_aes_key_set_apqns; zpc_aes_key_import_clear; zpc_aes_key_import; zpc_aes_key_export; zpc_aes_key_generate; zpc_aes_key_reencipher; zpc_aes_key_free; zpc_aes_ecb_alloc; zpc_aes_ecb_set_key; zpc_aes_ecb_encrypt; zpc_aes_ecb_decrypt; zpc_aes_ecb_free; zpc_aes_cbc_alloc; zpc_aes_cbc_set_key; zpc_aes_cbc_set_iv; zpc_aes_cbc_encrypt; zpc_aes_cbc_decrypt; zpc_aes_cbc_free; zpc_aes_xts_alloc; zpc_aes_xts_set_key; zpc_aes_xts_set_iv; zpc_aes_xts_encrypt; zpc_aes_xts_decrypt; zpc_aes_xts_free; zpc_aes_cmac_alloc; zpc_aes_cmac_set_key; zpc_aes_cmac_sign; zpc_aes_cmac_verify; zpc_aes_cmac_free; zpc_aes_ccm_alloc; zpc_aes_ccm_set_key; zpc_aes_ccm_set_iv; zpc_aes_ccm_encrypt; zpc_aes_ccm_decrypt; zpc_aes_ccm_free; zpc_aes_gcm_alloc; zpc_aes_gcm_set_key; zpc_aes_gcm_set_iv; zpc_aes_gcm_encrypt; zpc_aes_gcm_decrypt; zpc_aes_gcm_free; local: *; }; libzpc-1.0.0/libzpc.pc.in000066400000000000000000000003621413160260300152040ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ Name: @PROJECT_NAME@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ libzpc-1.0.0/misc/000077500000000000000000000000001413160260300137225ustar00rootroot00000000000000libzpc-1.0.0/misc/nist2json_aes_cbc.pl000077500000000000000000000043751413160260300176630ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; my ($out, $fdout) = ("nist_aes_cbc.json"); my ($state, $i, $first) = (0, 0, 1); my ($bufpre, $buf, $bufpost) = ("", "", ""); my ($in, $fdin, $line); my ($keylen) = (undef); my ($count, $countre) = ("", '^COUNT = (\d+)'); my ($key, $keyre) = ("", '^KEY = ([0-9a-f]*)'); my ($iv, $ivre) = ("", '^IV = ([0-9a-f]*)'); my ($ct, $ctre) = ("", '^CIPHERTEXT = ([0-9a-f]*)'); my ($pt, $ptre) = ("", '^PLAINTEXT = ([0-9a-f]*)'); sub print_begin_tests { $buf .= ",\n" if ($first != 1); $buf .= <<__; { "ivSize" : 128, "keySize" : $keylen, "tests" : [ __ $keylen = undef; $first = 0; } sub print_test { $buf .= ",\n" if ($state == 2); $buf .= <<__; { "tcId" : $i, "comment" : "$count", "key" : "$key", "iv" : "$iv", "msg" : "$pt", "ct" : "$ct" __ $buf .= " }"; $i = $i + 1; $key = ""; $iv = ""; $ct = ""; $pt = ""; } sub print_end_tests { $buf .= "\n ]\n"; $buf .= " }"; } printf("Parsing NIST AES-CBC test vectors ...\n"); for (@ARGV) { $in=$_; open($fdin, '<', $in) || die("ERROR: couldn't open $in ($!)."); $keylen = 128 if ($in =~ /128/); $keylen = 192 if ($in =~ /192/); $keylen = 256 if ($in =~ /256/); print_begin_tests(); $state = 0; while ($line = <$fdin>) { chomp($line); $key = $1 if ($line =~ /$keyre/); $iv = $1 if ($line =~ /$ivre/); $ct = $1 if ($line =~ /$ctre/); $pt = $1 if ($line =~ /$ptre/); if ($state == 0 && $line =~ /$countre/) { $state = 1; next; } if ($state == 1 && $line =~ /$countre/) { print_test(); $state = 2; next; } if ($state == 2 && $line =~ /$countre/) { print_test(); next; } } print_test(); print_end_tests(); close($fdin); } $bufpre = <<__; { "algorithm" : "AES-CBC", "numberOfTests" : $i, "testGroups" : [ __ $bufpost = "\n ]\n}"; $buf = $bufpre . $buf . $bufpost; # Expect 60 printf("$i test vectors found.\n"); open($fdout, '>', $out) || die("ERROR: couldn't open $out ($!)."); print({$fdout}$buf); close($fdout); libzpc-1.0.0/misc/nist2json_aes_ecb.pl000077500000000000000000000041541413160260300176600ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; my ($out, $fdout) = ("nist_aes_ecb.json"); my ($state, $i, $first) = (0, 0, 1); my ($bufpre, $buf, $bufpost) = ("", "", ""); my ($in, $fdin, $line); my ($keylen) = (undef); my ($count, $countre) = ("", '^COUNT = (\d+)'); my ($key, $keyre) = ("", '^KEY = ([0-9a-f]*)'); my ($ct, $ctre) = ("", '^CIPHERTEXT = ([0-9a-f]*)'); my ($pt, $ptre) = ("", '^PLAINTEXT = ([0-9a-f]*)'); sub print_begin_tests { $buf .= ",\n" if ($first != 1); $buf .= <<__; { "keySize" : $keylen, "tests" : [ __ $keylen = undef; $first = 0; } sub print_test { $buf .= ",\n" if ($state == 2); $buf .= <<__; { "tcId" : $i, "comment" : "$count", "key" : "$key", "msg" : "$pt", "ct" : "$ct" __ $buf .= " }"; $i = $i + 1; $key = ""; $ct = ""; $pt = ""; } sub print_end_tests { $buf .= "\n ]\n"; $buf .= " }"; } printf("Parsing NIST AES-CBC test vectors ...\n"); for (@ARGV) { $in=$_; open($fdin, '<', $in) || die("ERROR: couldn't open $in ($!)."); $keylen = 128 if ($in =~ /128/); $keylen = 192 if ($in =~ /192/); $keylen = 256 if ($in =~ /256/); print_begin_tests(); $state = 0; while ($line = <$fdin>) { chomp($line); $key = $1 if ($line =~ /$keyre/); $ct = $1 if ($line =~ /$ctre/); $pt = $1 if ($line =~ /$ptre/); if ($state == 0 && $line =~ /$countre/) { $state = 1; next; } if ($state == 1 && $line =~ /$countre/) { print_test(); $state = 2; next; } if ($state == 2 && $line =~ /$countre/) { print_test(); next; } } print_test(); print_end_tests(); close($fdin); } $bufpre = <<__; { "algorithm" : "AES-ECB", "numberOfTests" : $i, "testGroups" : [ __ $bufpost = "\n ]\n}"; $buf = $bufpre . $buf . $bufpost; # Expect 60 printf("$i test vectors found.\n"); open($fdout, '>', $out) || die("ERROR: couldn't open $out ($!)."); print({$fdout}$buf); close($fdout); libzpc-1.0.0/misc/nist2json_aes_gcm.pl000077500000000000000000000072451413160260300177010ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; my ($out, $fdout) = ("nist_aes_gcm.json"); my ($state, $i, $j) = (0, 0, 0); my ($bufpre, $buf, $bufpost, $deconly) = ("", "", "", ""); my ($in, $fdin, $line); my ($keylen, $keylenre) = (undef, '^\[Keylen = (128|192|256)\]'); my ($ivlen, $ivlenre) = (undef, '^\[IVlen = (\d+)\]'); my ($ptlen, $ptlenre) = (undef, '^\[PTlen = (\d+)\]'); my ($aadlen, $aadlenre) = (undef, '^\[AADlen = (\d+)\]'); my ($taglen, $taglenre) = (undef, '^\[Taglen = (\d+)\]'); my ($count, $countre) = ("", '^Count = (\d+)'); my ($key, $keyre) = ("", '^Key = ([0-9a-f]*)'); my ($iv, $ivre) = ("", '^IV = ([0-9a-f]*)'); my ($ct, $ctre) = ("", '^CT = ([0-9a-f]*)'); my ($aad, $aadre) = ("", '^AAD = ([0-9a-f]*)'); my ($tag, $tagre) = ("", '^Tag = ([0-9a-f]*)'); my ($pt, $ptre) = ("", '^PT = ([0-9a-f]*)'); my ($result, $resultre) = ("valid", '^FAIL'); sub print_begin_tests { $buf .= ",\n" if ($state != 0); $buf .= <<__; { "ivSize" : $ivlen, "keySize" : $keylen, "tagSize" : $taglen, "tests" : [ __ $keylen = undef; $ivlen = undef; $taglen = undef; $ptlen = undef; $aadlen = undef; } sub print_test { $buf .= ",\n" if ($state != 1); $buf .= <<__; { "tcId" : $i, "comment" : "$count", "key" : "$key", "iv" : "$iv", "aad" : "$aad", "msg" : "$pt", "ct" : "$ct", "tag" : "$tag", "result" : "$result", "flags" : [$deconly] __ $buf .= " }"; $i = $i + 1; $key = ""; $iv = ""; $ct = ""; $aad = ""; $tag = ""; $pt = ""; $result = "valid"; } sub print_end_tests { $buf .= "\n ]\n"; $buf .= " }"; } printf("Parsing NIST AES-GCM test vectors ...\n"); for (@ARGV) { $in=$_; open($fdin, '<', $in) || die("ERROR: couldn't open $in ($!)."); if ($in =~ /Decrypt/) { $deconly = "\"DecryptOnly\""; } else { $deconly = ""; } while ($line = <$fdin>) { chomp($line); $keylen = $1 if ($line =~ /$keylenre/); $ivlen = $1 if ($line =~ /$ivlenre/); $taglen = $1 if ($line =~ /$taglenre/); $ptlen = $1 if ($line =~ /$ptlenre/); $aadlen = $1 if ($line =~ /$aadlenre/); $key = $1 if ($line =~ /$keyre/); $iv = $1 if ($line =~ /$ivre/); $ct = $1 if ($line =~ /$ctre/); $aad = $1 if ($line =~ /$aadre/); $tag = $1 if ($line =~ /$tagre/); $pt = $1 if ($line =~ /$ptre/); $result ="invalid" if ($line =~ /$resultre/); if ($state == 0 && $line =~ /$countre/) { print_begin_tests(); $state = 1; $j = $j + 1; next; } if ($state == 1 && $line =~ /$countre/) { print_test(); $state = 2; $j = $j + 1; next; } if ($state == 2 && $line =~ /$countre/) { print_test(); $j = $j + 1; next; } if ($state == 2 && $line =~ /$keylenre/) { print_test(); $state = 3; next; } if ($state == 3 && $line =~ /$countre/) { print_end_tests(); print_begin_tests(); $state = 1; $j = $j + 1; next; } } close($fdin); } print_test(); print_end_tests(); $bufpre = <<__; { "algorithm" : "AES-GCM", "numberOfTests" : $i, "testGroups" : [ __ $bufpost = "\n ]\n}"; $buf = $bufpre . $buf . $bufpost; # Expect 47250 printf("$i test vectors found.\n"); if ($i != $j) { die ("ERROR: expected $j test vectors"); } open($fdout, '>', $out) || die("ERROR: couldn't open $out ($!)."); print({$fdout}$buf); close($fdout); libzpc-1.0.0/misc/nist2json_aes_xts.pl000077500000000000000000000045001413160260300177400ustar00rootroot00000000000000#!/usr/bin/env perl use strict; use warnings; my ($out, $fdout) = ("nist_aes_xts.json"); my ($state, $i, $first) = (0, 0, 1); my ($bufpre, $buf, $bufpost) = ("", "", ""); my ($in, $fdin, $line); my ($keylen) = (undef); my ($count, $countre) = ("", '^COUNT = (\d+)'); my ($bits, $bitsre) = ("", '^DataUnitLen = (\d+)'); my ($key, $keyre) = ("", '^Key = ([0-9a-f]*)'); my ($iv, $ivre) = ("", '^i = ([0-9a-f]*)'); my ($pt, $ptre) = ("", '^PT = ([0-9a-f]*)'); my ($ct, $ctre) = ("", '^CT = ([0-9a-f]*)'); sub print_begin_tests { $buf .= ",\n" if ($first != 1); $buf .= <<__; { "keySize" : $keylen, "tests" : [ __ $keylen = undef; $first = 0; } sub print_test { return if ($bits % 8 != 0); $buf .= ",\n" if ($state == 2); $buf .= <<__; { "tcId" : $i, "comment" : "$count", "key" : "$key", "iv" : "$iv", "msg" : "$pt", "ct" : "$ct" __ $buf .= " }"; $i = $i + 1; $bits = "", $key = ""; $iv=""; $ct = ""; $pt = ""; } sub print_end_tests { $buf .= "\n ]\n"; $buf .= " }"; } printf("Parsing NIST AES-XTS test vectors ...\n"); for (@ARGV) { $in=$_; open($fdin, '<', $in) || die("ERROR: couldn't open $in ($!)."); $keylen = 128 if ($in =~ /128/); $keylen = 256 if ($in =~ /256/); print_begin_tests(); $state = 0; while ($line = <$fdin>) { chomp($line); $bits = $1 if ($line =~ /$bitsre/); $key = $1 if ($line =~ /$keyre/); $iv = $1 if ($line =~ /$ivre/); $ct = $1 if ($line =~ /$ctre/); $pt = $1 if ($line =~ /$ptre/); if ($state == 0 && $line =~ /$countre/) { $state = 1; next; } if ($state == 1 && $line =~ /$countre/) { print_test(); $state = 2; next; } if ($state == 2 && $line =~ /$countre/) { print_test(); next; } } print_test(); print_end_tests(); close($fdin); } $bufpre = <<__; { "algorithm" : "AES-XTS", "numberOfTests" : $i, "testGroups" : [ __ $bufpost = "\n ]\n}"; $buf = $bufpre . $buf . $bufpost; # Expect 60 printf("$i test vectors found.\n"); open($fdout, '>', $out) || die("ERROR: couldn't open $out ($!)."); print({$fdout}$buf); close($fdout); libzpc-1.0.0/src/000077500000000000000000000000001413160260300135565ustar00rootroot00000000000000libzpc-1.0.0/src/aes_cbc.c000066400000000000000000000216051413160260300153050ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include "zpc/aes_cbc.h" #include "zpc/error.h" #include "aes_cbc_local.h" #include "aes_key_local.h" #include "cpacf.h" #include "globals.h" #include "misc.h" #include "debug.h" #include "zkey/pkey.h" #include #include #include #include #include static void __aes_cbc_set_iv(struct zpc_aes_cbc *, const u8 *); static int __aes_cbc_crypt(struct zpc_aes_cbc *, u8 *, const u8 *, size_t, unsigned long); static void __aes_cbc_reset(struct zpc_aes_cbc *); static void __aes_cbc_reset_iv(struct zpc_aes_cbc *); int zpc_aes_cbc_alloc(struct zpc_aes_cbc **aes_cbc) { struct zpc_aes_cbc *new_aes_cbc = NULL; int rc; if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_cbc) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_cbc == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } new_aes_cbc = calloc(1, sizeof(*new_aes_cbc)); if (new_aes_cbc == NULL) { rc = ZPC_ERROR_MALLOC; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } DEBUG("aes-cbc context at %p: allocated", new_aes_cbc); *aes_cbc = new_aes_cbc; rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_cbc_set_key(struct zpc_aes_cbc *aes_cbc, struct zpc_aes_key *aes_key) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_cbc) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_cbc == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-cbc context at %p: key unset", aes_cbc); __aes_cbc_reset(aes_cbc); rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); rc = aes_key_check(aes_key); if (rc) goto ret; if (aes_cbc->aes_key == aes_key) { DEBUG("aes-cbc context at %p: key at %p already set", aes_cbc, aes_key); rc = 0; /* nothing to do */ goto ret; } aes_key->refcount++; DEBUG("aes key at %p: refcount %llu", aes_key, aes_key->refcount); if (aes_cbc->key_set) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-cbc context at %p: key unset", aes_cbc); __aes_cbc_reset(aes_cbc); } /* Set new key. */ assert(!aes_cbc->key_set); DEBUG("aes-cbc context at %p: key at %p set", aes_cbc, aes_key); memcpy(aes_cbc->param.protkey, aes_key->prot.protkey, sizeof(aes_cbc->param.protkey)); aes_cbc->fc = CPACF_KMC_ENCRYPTED_AES_128 + (aes_key->keysize - 128) / 64; aes_cbc->aes_key = aes_key; aes_cbc->key_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_cbc_set_iv(struct zpc_aes_cbc *aes_cbc, const u8 * iv) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_cbc) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_cbc == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if (iv == NULL) { /* Unset iv */ DEBUG("aes-cbc context at %p: iv unset", aes_cbc); __aes_cbc_reset_iv(aes_cbc); aes_cbc->iv_set = 0; rc = 0; goto ret; } if (aes_cbc->key_set != 1) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } __aes_cbc_set_iv(aes_cbc, iv); DEBUG("aes-cbc context at %p: iv set", aes_cbc); aes_cbc->iv_set = 1; rc = 0; ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_cbc_encrypt(struct zpc_aes_cbc *aes_cbc, u8 * c, const u8 * m, size_t mlen) { struct cpacf_kmc_aes_param *param; struct pkey_protkey *protkey; unsigned long flags = 0; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_cbc) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_cbc == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((mlen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if ((mlen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (mlen % 16 != 0) { rc = ZPC_ERROR_MLEN; } if (!aes_cbc->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_cbc->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_cbc->aes_key->prot; param = &aes_cbc->param; for (;;) { rc = __aes_cbc_crypt(aes_cbc, c, m, mlen, flags); if (rc == 0) { break; } else { if (aes_cbc->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_cbc-> aes_key->lock); assert(rv == 0); DEBUG ("aes-cbc context at %p: re-derive protected key from %s secure key from aes key at %p", aes_cbc, i == 0 ? "current" : "old", aes_cbc->aes_key); rc = aes_key_sec2prot(aes_cbc->aes_key, i); memcpy(param->protkey, protkey->protkey, sizeof(param->protkey)); rv = pthread_mutex_unlock(&aes_cbc-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_cbc_decrypt(struct zpc_aes_cbc *aes_cbc, u8 * m, const u8 * c, size_t clen) { struct cpacf_kmc_aes_param *param; struct pkey_protkey *protkey; unsigned long flags = CPACF_M; /* decrypt */ int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_cbc) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_cbc == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((clen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if ((clen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (clen % 16 != 0) { rc = ZPC_ERROR_CLEN; goto ret; } if (!aes_cbc->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_cbc->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_cbc->aes_key->prot; param = &aes_cbc->param; for (;;) { rc = __aes_cbc_crypt(aes_cbc, m, c, clen, flags); if (rc == 0) { break; } else { if (aes_cbc->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_cbc-> aes_key->lock); assert(rv == 0); DEBUG ("aes-cbc context at %p: re-derive protected key from %s secure key from aes key at %p", aes_cbc, i == 0 ? "current" : "old", aes_cbc->aes_key); rc = aes_key_sec2prot(aes_cbc->aes_key, i); memcpy(param->protkey, protkey->protkey, sizeof(param->protkey)); rv = pthread_mutex_unlock(&aes_cbc-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } void zpc_aes_cbc_free(struct zpc_aes_cbc **aes_cbc) { if (aes_cbc == NULL) return; if (*aes_cbc == NULL) return; if ((*aes_cbc)->key_set) { /* Decrease aes_key's refcount. */ zpc_aes_key_free(&(*aes_cbc)->aes_key); (*aes_cbc)->key_set = 0; __aes_cbc_reset_iv(*aes_cbc); (*aes_cbc)->iv_set = 0; } __aes_cbc_reset(*aes_cbc); free(*aes_cbc); *aes_cbc = NULL; DEBUG("return"); } static void __aes_cbc_set_iv(struct zpc_aes_cbc *aes_cbc, const u8 * iv) { assert(aes_cbc != NULL); assert(iv != NULL); memcpy(aes_cbc->param.cv, iv, 16); } static int __aes_cbc_crypt(struct zpc_aes_cbc *aes_cbc, u8 * out, const u8 * in, size_t inlen, unsigned long flags) { struct cpacf_kmc_aes_param *param; int rc, cc; param = &aes_cbc->param; cc = cpacf_kmc(aes_cbc->fc | flags, param, out, in, inlen); assert(cc == 0 || cc == 1 || cc == 2); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto err; } rc = 0; err: return rc; } static void __aes_cbc_reset(struct zpc_aes_cbc *aes_cbc) { assert(aes_cbc != NULL); memset(&aes_cbc->param, 0, sizeof(aes_cbc->param)); __aes_cbc_reset_iv(aes_cbc); aes_cbc->iv_set = 0; if (aes_cbc->aes_key != NULL) zpc_aes_key_free(&aes_cbc->aes_key); aes_cbc->key_set = 0; aes_cbc->fc = 0; } static void __aes_cbc_reset_iv(struct zpc_aes_cbc *aes_cbc) { assert(aes_cbc != NULL); memset(aes_cbc->param.cv, 0, sizeof(aes_cbc->param.cv)); aes_cbc->iv_set = 0; } libzpc-1.0.0/src/aes_cbc_local.h000066400000000000000000000007301413160260300164600ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef AES_CBC_LOCAL_H # define AES_CBC_LOCAL_H # include "zpc/aes_key.h" # include "misc.h" # include "cpacf.h" /* * Internal aes_cbc interface. */ struct zpc_aes_cbc { struct cpacf_kmc_aes_param param; struct zpc_aes_key *aes_key; unsigned int fc; int key_set; int iv_set; }; #endif libzpc-1.0.0/src/aes_ccm.c000066400000000000000000000413571413160260300153260ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include "zpc/aes_ccm.h" #include "zpc/error.h" #include "aes_ccm_local.h" #include "aes_key_local.h" #include "cpacf.h" #include "globals.h" #include "misc.h" #include "debug.h" #include "zkey/pkey.h" #include #include #include #include #include struct aes_ccm_flags { u8 reserved:1; u8 adata:1; u8 m:3; u8 l:3; } __packed; static void __aes_ccm_set_iv(struct zpc_aes_ccm *, const u8 *, size_t); static int __aes_ccm_crypt(struct zpc_aes_ccm *, u8 *, u8 *, size_t, const u8 *, size_t, const u8 *, size_t, unsigned long); static int __aes_ccm_cbcmac(struct zpc_aes_ccm *, const u8 *, size_t); static int __aes_ccm_ctr(struct zpc_aes_ccm *, u8[16], u8 *, const u8 *, size_t); static void __aes_ccm_reset(struct zpc_aes_ccm *); static void __aes_ccm_reset_iv(struct zpc_aes_ccm *); int zpc_aes_ccm_alloc(struct zpc_aes_ccm **aes_ccm) { struct zpc_aes_ccm *new_aes_ccm = NULL; int rc; if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_ccm) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_ccm == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } new_aes_ccm = calloc(1, sizeof(*new_aes_ccm)); if (new_aes_ccm == NULL) { rc = ZPC_ERROR_MALLOC; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } DEBUG("aes-ccm context at %p: allocated", new_aes_ccm); *aes_ccm = new_aes_ccm; rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_ccm_set_key(struct zpc_aes_ccm *aes_ccm, struct zpc_aes_key *aes_key) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_ccm) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_ccm == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-ccm context at %p: key unset", aes_ccm); __aes_ccm_reset(aes_ccm); rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); rc = aes_key_check(aes_key); if (rc) goto ret; if (aes_ccm->aes_key == aes_key) { DEBUG("aes-ccm context at %p: key at %p already set", aes_ccm, aes_key); rc = 0; /* nothing to do */ goto ret; } aes_key->refcount++; DEBUG("aes key at %p: refcount %llu", aes_key, aes_key->refcount); if (aes_ccm->key_set) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-ccm context at %p: key unset", aes_ccm); __aes_ccm_reset(aes_ccm); } /* Set new key. */ assert(!aes_ccm->key_set); DEBUG("aes-ccm context at %p: key at %p set, iv unset", aes_ccm, aes_key); memcpy(aes_ccm->param_kma.protkey, aes_key->prot.protkey, sizeof(aes_ccm->param_kma.protkey)); memcpy(aes_ccm->param_kmac.protkey, aes_key->prot.protkey, sizeof(aes_ccm->param_kmac.protkey)); /* The corresponding KMAC function codes are the same as the KMA * function codes. */ aes_ccm->fc = CPACF_KMA_GCM_ENCRYPTED_AES_128 + (aes_key->keysize - 128) / 64; aes_ccm->aes_key = aes_key; aes_ccm->key_set = 1; __aes_ccm_reset_iv(aes_ccm); aes_ccm->iv_set = 0; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_ccm_set_iv(struct zpc_aes_ccm *aes_ccm, const u8 * iv, size_t ivlen) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_ccm) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_ccm == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if (iv == NULL) { /* Unset iv */ DEBUG("aes-ccm context at %p: iv unset", aes_ccm); __aes_ccm_reset_iv(aes_ccm); aes_ccm->iv_set = 0; rc = 0; goto ret; } /* 15 - L byte nonce. 2 <= L <= 8. */ if (ivlen < 15 - 8 || ivlen > 15 - 2) { rc = ZPC_ERROR_IVSIZE; goto ret; } if (aes_ccm->key_set != 1) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } __aes_ccm_set_iv(aes_ccm, iv, ivlen); DEBUG("aes-ccm context at %p: iv set", aes_ccm); aes_ccm->iv_set = 1; rc = 0; ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_ccm_encrypt(struct zpc_aes_ccm *aes_ccm, u8 * c, u8 * tag, size_t taglen, const u8 * aad, size_t aadlen, const u8 * m, size_t mlen) { struct cpacf_kma_gcm_aes_param *param_kma; struct cpacf_kmac_aes_param *param_kmac; struct pkey_protkey *protkey; unsigned long flags = 0; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_ccm) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_ccm == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((mlen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } /* Valid tag byte-lengths: 16, 14, 12, 10, 8, 6, 4. */ if (taglen > 0 && tag == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (taglen % 2 != 0 || taglen > 16 || taglen < 4) { rc = ZPC_ERROR_TAGSIZE; goto ret; } /* 0 <= aad byte-length <= 2^64 - 1 */ if (aadlen > 0 && aad == NULL) { rc = ZPC_ERROR_ARG5NULL; goto ret; } if (!aes_ccm->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_ccm->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } /* 0 <= m byte-length <= 2^(8L) - 1 */ if ((mlen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG7NULL; goto ret; } if (aes_ccm->ivlen > 7 && (u64) mlen > (1ULL << (8 * (15 - aes_ccm->ivlen))) - 1) { rc = ZPC_ERROR_MLEN; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_ccm->aes_key->prot; param_kma = &aes_ccm->param_kma; param_kmac = &aes_ccm->param_kmac; for (;;) { rc = __aes_ccm_crypt(aes_ccm, c, tag, taglen, aad, aadlen, m, mlen, flags); if (rc == 0) { break; } else { if (aes_ccm->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_ccm-> aes_key->lock); assert(rv == 0); DEBUG ("aes-ccm context at %p: re-derive protected key from %s secure key from aes key at %p", aes_ccm, i == 0 ? "current" : "old", aes_ccm->aes_key); rc = aes_key_sec2prot(aes_ccm->aes_key, i); memcpy(param_kma->protkey, protkey->protkey, sizeof(param_kma->protkey)); memcpy(param_kmac->protkey, protkey->protkey, sizeof(param_kmac->protkey)); rv = pthread_mutex_unlock(&aes_ccm-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_ccm_decrypt(struct zpc_aes_ccm *aes_ccm, u8 * m, const u8 * tag, size_t taglen, const u8 * aad, size_t aadlen, const u8 * c, size_t clen) { struct cpacf_kma_gcm_aes_param *param_kma; struct cpacf_kmac_aes_param *param_kmac; struct pkey_protkey *protkey; unsigned long flags = CPACF_M; int rc, rv, i; u8 tmp[16]; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_ccm) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_ccm == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((clen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } /* Valid tag byte-lengths: 16, 14, 12, 10, 8, 6, 4. */ if (taglen > 0 && tag == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (taglen % 2 != 0 || taglen > 16 || taglen < 4) { rc = ZPC_ERROR_TAGSIZE; goto ret; } /* 0 <= aad byte-length <= 2^64 - 1 */ if (aadlen > 0 && aad == NULL) { rc = ZPC_ERROR_ARG5NULL; goto ret; } if (!aes_ccm->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_ccm->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } /* 0 <= c byte-length <= 2^(8L) - 1 */ if ((clen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG7NULL; goto ret; } if (aes_ccm->ivlen > 7 && (u64) clen > (1ULL << (8 * (15 - aes_ccm->ivlen))) - 1) { rc = ZPC_ERROR_CLEN; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0 && (rc != ZPC_ERROR_TAGMISMATCH); i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_ccm->aes_key->prot; param_kma = &aes_ccm->param_kma; param_kmac = &aes_ccm->param_kmac; for (;;) { memcpy(tmp, tag, taglen); rc = __aes_ccm_crypt(aes_ccm, m, tmp, taglen, aad, aadlen, c, clen, flags); if (rc == 0 || rc == ZPC_ERROR_TAGMISMATCH) { break; } else { if (aes_ccm->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_ccm-> aes_key->lock); assert(rv == 0); DEBUG ("aes-ccm context at %p: re-derive protected key from %s secure key from aes key at %p", aes_ccm, i == 0 ? "current" : "old", aes_ccm->aes_key); rc = aes_key_sec2prot(aes_ccm->aes_key, i); memcpy(param_kma->protkey, protkey->protkey, sizeof(param_kma->protkey)); memcpy(param_kmac->protkey, protkey->protkey, sizeof(param_kmac->protkey)); rv = pthread_mutex_unlock(&aes_ccm-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } void zpc_aes_ccm_free(struct zpc_aes_ccm **aes_ccm) { if (aes_ccm == NULL) return; if (*aes_ccm == NULL) return; if ((*aes_ccm)->key_set) { /* Decrease aes_key's refcount. */ zpc_aes_key_free(&(*aes_ccm)->aes_key); (*aes_ccm)->key_set = 0; __aes_ccm_reset_iv(*aes_ccm); (*aes_ccm)->iv_set = 0; } __aes_ccm_reset(*aes_ccm); free(*aes_ccm); *aes_ccm = NULL; DEBUG("return"); } static void __aes_ccm_set_iv(struct zpc_aes_ccm *aes_ccm, const u8 * iv, size_t ivlen) { assert(aes_ccm != NULL); assert(iv != NULL); memset(aes_ccm->param_kma.reserved, 0, sizeof(aes_ccm->param_kma.reserved)); memset(aes_ccm->param_kma.t, 0, sizeof(aes_ccm->param_kma.t)); memset(aes_ccm->param_kma.h, 0, sizeof(aes_ccm->param_kma.h)); memset(aes_ccm->param_kma.j0, 0, sizeof(aes_ccm->param_kma.j0)); aes_ccm->param_kma.cv = 0; aes_ccm->param_kma.taadl = 0; aes_ccm->param_kma.tpcl = 0; memset(aes_ccm->param_kmac.icv, 0, sizeof(aes_ccm->param_kmac.icv)); memset(aes_ccm->iv, 0, sizeof(aes_ccm->iv)); aes_ccm->ivlen = ivlen; memcpy(aes_ccm->iv, iv, ivlen); } static int __aes_ccm_crypt(struct zpc_aes_ccm *aes_ccm, u8 * out, u8 * tag, size_t taglen, const u8 * aad, size_t aadlen, const u8 * in, size_t inlen, unsigned long flags) { struct aes_ccm_flags b0flags; u8 b01[32], tmp[16]; int rc, cc; size_t rem, i; assert(aes_ccm != NULL); assert(aes_ccm->key_set == 1); assert(aes_ccm->iv_set == 1); memset(&b0flags, 0, sizeof(b0flags)); memset(b01, 0, sizeof(b01)); if (aadlen) b0flags.adata = 1; b0flags.m = taglen / 2 - 1; assert(b0flags.m != 0); b0flags.l = (15 - aes_ccm->ivlen) - 1; assert(b0flags.l != 0); memcpy(b01, &b0flags, 1); memcpy(b01 + 1, aes_ccm->iv, aes_ccm->ivlen); for (i = 0; i < 16 - 1 - aes_ccm->ivlen; i++) b01[15 - i] = ((u8 *) & inlen)[sizeof(inlen) - 1 - i]; if (b0flags.adata == 1) { if (aadlen < (1ULL << 16) - (1ULL << 8)) { *(u16 *) (&(b01[16])) = aadlen; i = 16 + 2; } else if (aadlen <= 1ULL << 32) { *(u16 *) (&(b01[16])) = 0xfffe; *(u32 *) (&(b01[16])) = aadlen; i = 16 + 6; } else { *(u16 *) (&(b01[16])) = 0xffff; *(u64 *) (&(b01[16])) = aadlen; i = 16 + 10; } while (i < 32 && aadlen) { b01[i] = *aad; aad++; aadlen--; i++; } while (i < 32) { b01[i] = 0; i++; } } memset(aes_ccm->param_kmac.icv, 0, sizeof(aes_ccm->param_kmac.icv)); cc = cpacf_kmac(aes_ccm->fc, &aes_ccm->param_kmac, b01, b0flags.adata == 1 ? 32 : 16); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } rem = aadlen & 0xf; aadlen &= ~(size_t)0xf; if (aadlen) { cc = cpacf_kmac(aes_ccm->fc, &aes_ccm->param_kmac, aad, aadlen); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } aad += aadlen; } if (rem) { for (i = 0; i < rem; i++) tmp[i] = aad[i]; for (; i < 16; i++) tmp[i] = 0; cc = cpacf_kmac(aes_ccm->fc, &aes_ccm->param_kmac, tmp, 16); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } } memset(tmp, 0, 16); if (!(flags & CPACF_M)) { /* mac-then-encrypt */ rc = __aes_ccm_cbcmac(aes_ccm, in, inlen); if (rc) goto ret; rc = __aes_ccm_ctr(aes_ccm, tmp, out, in, inlen); if (rc) goto ret; for (i = 0; i < 16; i++) tmp[i] ^= aes_ccm->param_kmac.icv[i]; memcpy(tag, tmp, taglen); } else { /* decrypt-then-mac */ rc = __aes_ccm_ctr(aes_ccm, tmp, out, in, inlen); if (rc) goto ret; rc = __aes_ccm_cbcmac(aes_ccm, out, inlen); if (rc) goto ret; for (i = 0; i < taglen; i++) tmp[i] ^= tag[i]; rc = memcmp_consttime(tmp, aes_ccm->param_kmac.icv, taglen); if (rc) { rc = ZPC_ERROR_TAGMISMATCH; goto ret; } } rc = 0; ret: if (rc == ZPC_ERROR_TAGMISMATCH) { memset(out, 0, inlen); } return rc; } static int __aes_ccm_cbcmac(struct zpc_aes_ccm *aes_ccm, const u8 * in, size_t inlen) { struct aes_ccm_flags aflags; u8 a[16], tmp[16]; int rc, cc; size_t rem, i; memset(&aflags, 0, sizeof(aflags)); memset(a, 0, sizeof(a)); rem = inlen & 0xf; inlen &= ~(size_t)0xf; if (inlen) { cc = cpacf_kmac(aes_ccm->fc, &aes_ccm->param_kmac, in, inlen); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } } if (rem) { for (i = 0; i < rem; i++) tmp[i] = in[inlen + i]; for (; i < 16; i++) tmp[i] = 0; cc = cpacf_kmac(aes_ccm->fc, &aes_ccm->param_kmac, tmp, 16); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } } rc = 0; ret: return rc; } static int __aes_ccm_ctr(struct zpc_aes_ccm *aes_ccm, u8 tagkey[16], u8 * out, const u8 * in, size_t inlen) { struct aes_ccm_flags aflags; unsigned int flags; u8 a[16]; int rc, cc; u32 ctr; flags = CPACF_KMA_LAAD | CPACF_KMA_HS; memset(&aflags, 0, sizeof(aflags)); memset(a, 0, sizeof(a)); aflags.l = (15 - aes_ccm->ivlen) - 1; assert(aflags.l != 0); memcpy(a, &aflags, 1); memcpy(a + 1, aes_ccm->iv, aes_ccm->ivlen); memcpy(&ctr, a + 16 - 4, 4); ctr--; /* KMA pre-inc */ memcpy(a + 16 - 4, &ctr, 4); memset(aes_ccm->param_kma.reserved, 0, sizeof(aes_ccm->param_kma.reserved)); aes_ccm->param_kma.cv = ctr; memcpy(aes_ccm->param_kma.j0, a, 16); memset(tagkey, 0, 16); cc = cpacf_kma(aes_ccm->fc | flags, &aes_ccm->param_kma, tagkey, NULL, 0, tagkey, 16); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } cc = cpacf_kma(aes_ccm->fc | flags | CPACF_KMA_LPC, &aes_ccm->param_kma, out, NULL, 0, in, inlen); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } rc = 0; ret: return rc; } static void __aes_ccm_reset(struct zpc_aes_ccm *aes_ccm) { assert(aes_ccm != NULL); memset(&aes_ccm->param_kma, 0, sizeof(aes_ccm->param_kma)); memset(&aes_ccm->param_kmac, 0, sizeof(aes_ccm->param_kmac)); __aes_ccm_reset_iv(aes_ccm); aes_ccm->iv_set = 0; if (aes_ccm->aes_key != NULL) zpc_aes_key_free(&aes_ccm->aes_key); aes_ccm->key_set = 0; aes_ccm->fc = 0; } static void __aes_ccm_reset_iv(struct zpc_aes_ccm *aes_ccm) { assert(aes_ccm != NULL); memset(aes_ccm->param_kma.reserved, 0, sizeof(aes_ccm->param_kma.reserved)); memset(aes_ccm->param_kma.t, 0, sizeof(aes_ccm->param_kma.t)); memset(aes_ccm->param_kma.h, 0, sizeof(aes_ccm->param_kma.h)); memset(aes_ccm->param_kma.j0, 0, sizeof(aes_ccm->param_kma.j0)); aes_ccm->param_kma.cv = 0; aes_ccm->param_kma.taadl = 0; aes_ccm->param_kma.tpcl = 0; memset(aes_ccm->param_kmac.icv, 0, sizeof(aes_ccm->param_kmac.icv)); memset(aes_ccm->iv, 0, sizeof(aes_ccm->iv)); aes_ccm->ivlen = 0; aes_ccm->iv_set = 0; } libzpc-1.0.0/src/aes_ccm_local.h000066400000000000000000000010451413160260300164730ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef AES_CCM_LOCAL_H # define AES_CCM_LOCAL_H # include "zpc/aes_key.h" # include "misc.h" # include "cpacf.h" /* * Internal aes_ccm interface. */ struct zpc_aes_ccm { struct cpacf_kma_gcm_aes_param param_kma; struct cpacf_kmac_aes_param param_kmac; struct zpc_aes_key *aes_key; unsigned int fc; u8 iv[16]; size_t ivlen; int key_set; int iv_set; }; #endif libzpc-1.0.0/src/aes_cmac.c000066400000000000000000000240401413160260300154550ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include "zpc/aes_cmac.h" #include "zpc/error.h" #include "aes_cmac_local.h" #include "aes_key_local.h" #include "cpacf.h" #include "globals.h" #include "misc.h" #include "debug.h" #include "zkey/pkey.h" #include #include #include #include #include static int __aes_cmac_crypt(struct zpc_aes_cmac *, u8 *, size_t, const u8 *, size_t, unsigned long); static void __aes_cmac_reset(struct zpc_aes_cmac *); static void __aes_cmac_reset_state(struct zpc_aes_cmac *); int zpc_aes_cmac_alloc(struct zpc_aes_cmac **aes_cmac) { struct zpc_aes_cmac *new_aes_cmac = NULL; int rc; if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_cmac) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_cmac == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } new_aes_cmac = calloc(1, sizeof(*new_aes_cmac)); if (new_aes_cmac == NULL) { rc = ZPC_ERROR_MALLOC; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } DEBUG("aes-cmac context at %p: allocated", new_aes_cmac); *aes_cmac = new_aes_cmac; rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_cmac_set_key(struct zpc_aes_cmac *aes_cmac, struct zpc_aes_key *aes_key) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_cmac) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_cmac == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-cmac context at %p: key unset", aes_cmac); __aes_cmac_reset(aes_cmac); rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); rc = aes_key_check(aes_key); if (rc) goto ret; if (aes_cmac->aes_key == aes_key) { __aes_cmac_reset_state(aes_cmac); DEBUG("aes-cmac context at %p: key at %p already set", aes_cmac, aes_key); rc = 0; goto ret; } aes_key->refcount++; DEBUG("aes key at %p: refcount %llu", aes_key, aes_key->refcount); if (aes_cmac->key_set) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-cmac context at %p: key unset", aes_cmac); __aes_cmac_reset(aes_cmac); } /* Set new key. */ assert(!aes_cmac->key_set); DEBUG("aes-cmac context at %p: key at %p set, iv unset", aes_cmac, aes_key); memset(&aes_cmac->param_kmac, 0, sizeof(aes_cmac->param_kmac)); memset(&aes_cmac->param_pcc, 0, sizeof(aes_cmac->param_pcc)); memcpy(aes_cmac->param_kmac.protkey, aes_key->prot.protkey, sizeof(aes_cmac->param_kmac.protkey)); memcpy(aes_cmac->param_pcc.protkey, aes_key->prot.protkey, sizeof(aes_cmac->param_pcc.protkey)); aes_cmac->fc = CPACF_KMAC_ENCRYPTED_AES_128 + (aes_key->keysize - 128) / 64; aes_cmac->aes_key = aes_key; aes_cmac->key_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_cmac_sign(struct zpc_aes_cmac *aes_cmac, u8 * tag, size_t taglen, const u8 * m, size_t mlen) { struct cpacf_kmac_aes_param *param_kmac; struct cpacf_pcc_cmac_aes_param *param_pcc; struct pkey_protkey *protkey; unsigned long flags = 0; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_cmac) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_cmac == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } /* Valid tag byte-lengths: >= 8, <= 16. */ if (taglen > 0 && tag == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if (tag != NULL && (taglen > 16 || taglen < 8)) { rc = ZPC_ERROR_TAGSIZE; goto ret; } if (mlen > 0 && mlen % 16 != 0 && tag == NULL) { rc = ZPC_ERROR_ARG5RANGE; goto ret; } if (!aes_cmac->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_cmac->aes_key->prot; param_kmac = &aes_cmac->param_kmac; param_pcc = &aes_cmac->param_pcc; for (;;) { rc = __aes_cmac_crypt(aes_cmac, tag, taglen, m, mlen, flags); if (rc == 0) { break; } else { if (aes_cmac->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_cmac-> aes_key->lock); assert(rv == 0); DEBUG ("aes-cmac context at %p: re-derive protected key from %s secure key from aes key at %p", aes_cmac, i == 0 ? "current" : "old", aes_cmac->aes_key); rc = aes_key_sec2prot(aes_cmac->aes_key, i); memcpy(param_kmac->protkey, protkey->protkey, sizeof(param_kmac->protkey)); memcpy(param_pcc->protkey, protkey->protkey, sizeof(param_pcc->protkey)); rv = pthread_mutex_unlock(&aes_cmac-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_cmac_verify(struct zpc_aes_cmac *aes_cmac, const u8 * tag, size_t taglen, const u8 * m, size_t mlen) { struct cpacf_kmac_aes_param *param_kmac; struct cpacf_pcc_cmac_aes_param *param_pcc; struct pkey_protkey *protkey; unsigned long flags = 0; int rc, rv, i; u8 tmp[16]; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_cmac) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_cmac == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } /* Valid tag byte-lengths: >= 8, <= 16. */ if (taglen > 0 && tag == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if (tag != NULL && (taglen > 16 || taglen < 8)) { rc = ZPC_ERROR_TAGSIZE; goto ret; } if (mlen > 0 && mlen % 16 != 0 && tag == NULL) { rc = ZPC_ERROR_ARG5RANGE; goto ret; } if (!aes_cmac->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && (rc != 0 && rc != ZPC_ERROR_TAGMISMATCH); i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_cmac->aes_key->prot; param_kmac = &aes_cmac->param_kmac; param_pcc = &aes_cmac->param_pcc; for (;;) { rc = __aes_cmac_crypt(aes_cmac, tag == NULL ? NULL : tmp, tag == NULL ? 0 : sizeof(tmp), m, mlen, flags); if (rc == 0) { if (tag != NULL) { rc = memcmp_consttime(tmp, tag, taglen); if (rc != 0) rc = ZPC_ERROR_TAGMISMATCH; } break; } else { if (aes_cmac->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_cmac-> aes_key->lock); assert(rv == 0); DEBUG ("aes-cmac context at %p: re-derive protected key from %s secure key from aes key at %p", aes_cmac, i == 0 ? "current" : "old", aes_cmac->aes_key); rc = aes_key_sec2prot(aes_cmac->aes_key, i); memcpy(param_kmac->protkey, protkey->protkey, sizeof(param_kmac->protkey)); memcpy(param_pcc->protkey, protkey->protkey, sizeof(param_pcc->protkey)); rv = pthread_mutex_unlock(&aes_cmac-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } void zpc_aes_cmac_free(struct zpc_aes_cmac **aes_cmac) { if (aes_cmac == NULL) return; if (*aes_cmac == NULL) return; if ((*aes_cmac)->key_set) { /* Decrease aes_key's refcount. */ zpc_aes_key_free(&(*aes_cmac)->aes_key); (*aes_cmac)->key_set = 0; } __aes_cmac_reset(*aes_cmac); free(*aes_cmac); *aes_cmac = NULL; DEBUG("return"); } static int __aes_cmac_crypt(struct zpc_aes_cmac *aes_cmac, u8 * tag, size_t taglen, const u8 * in, size_t inlen, unsigned long flags) { size_t rem; int rc, cc; assert(aes_cmac != NULL); assert((tag != NULL) || (tag == NULL && inlen % 16 == 0)); assert((tag == NULL) || (8 <= taglen && taglen <= 16)); rem = inlen & 0xf; inlen &= ~(size_t)0xf; if (tag != NULL && rem == 0 && inlen >= 16) { inlen -= 16; rem += 16; } if (inlen) { cc = cpacf_kmac(aes_cmac->fc | flags, &aes_cmac->param_kmac, in, inlen); assert(cc == 0 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto err; } in += inlen; } if (tag != NULL) { aes_cmac->param_pcc.ml = rem * 8; memset(aes_cmac->param_pcc.message, 0, sizeof(aes_cmac->param_pcc.message)); memcpy(aes_cmac->param_pcc.message, in, rem); memcpy(aes_cmac->param_pcc.icv, aes_cmac->param_kmac.icv, sizeof(aes_cmac->param_pcc.icv)); cc = cpacf_pcc(aes_cmac->fc | flags, &aes_cmac->param_pcc); assert(cc == 0 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto err; } memcpy(tag, aes_cmac->param_pcc.icv, taglen); __aes_cmac_reset_state(aes_cmac); } rc = 0; err: return rc; } static void __aes_cmac_reset(struct zpc_aes_cmac *aes_cmac) { assert(aes_cmac != NULL); __aes_cmac_reset_state(aes_cmac); memset(&aes_cmac->param_kmac, 0, sizeof(aes_cmac->param_kmac)); memset(&aes_cmac->param_pcc, 0, sizeof(aes_cmac->param_pcc)); if (aes_cmac->aes_key != NULL) zpc_aes_key_free(&aes_cmac->aes_key); aes_cmac->key_set = 0; aes_cmac->fc = 0; } static void __aes_cmac_reset_state(struct zpc_aes_cmac *aes_cmac) { assert(aes_cmac != NULL); memset(aes_cmac->param_kmac.icv, 0, sizeof(aes_cmac->param_kmac.icv)); memset(&aes_cmac->param_pcc.icv, 0, sizeof(aes_cmac->param_pcc.icv)); memset(&aes_cmac->param_pcc.message, 0, sizeof(aes_cmac->param_pcc.message)); aes_cmac->param_pcc.ml = 0; } libzpc-1.0.0/src/aes_cmac_local.h000066400000000000000000000010011413160260300166240ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef AES_CMAC_LOCAL_H # define AES_CMAC_LOCAL_H # include "zpc/aes_key.h" # include "misc.h" # include "cpacf.h" /* * Internal aes_cmac interface. */ struct zpc_aes_cmac { struct cpacf_kmac_aes_param param_kmac; struct cpacf_pcc_cmac_aes_param param_pcc; struct zpc_aes_key *aes_key; unsigned int fc; int key_set; }; #endif libzpc-1.0.0/src/aes_ecb.c000066400000000000000000000167741413160260300153220ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include "zpc/aes_ecb.h" #include "zpc/error.h" #include "aes_ecb_local.h" #include "aes_key_local.h" #include "cpacf.h" #include "globals.h" #include "misc.h" #include "debug.h" #include "zkey/pkey.h" #include #include #include #include #include static int __aes_ecb_crypt(struct zpc_aes_ecb *, u8 *, const u8 *, size_t, unsigned long); static void __aes_ecb_reset(struct zpc_aes_ecb *); int zpc_aes_ecb_alloc(struct zpc_aes_ecb **aes_ecb) { struct zpc_aes_ecb *new_aes_ecb = NULL; int rc; if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_ecb) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_ecb == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } new_aes_ecb = calloc(1, sizeof(*new_aes_ecb)); if (new_aes_ecb == NULL) { rc = ZPC_ERROR_MALLOC; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } DEBUG("aes-ecb context at %p: allocated", new_aes_ecb); *aes_ecb = new_aes_ecb; rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_ecb_set_key(struct zpc_aes_ecb *aes_ecb, struct zpc_aes_key *aes_key) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_ecb) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_ecb == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-ecb context at %p: key unset", aes_ecb); __aes_ecb_reset(aes_ecb); rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); rc = aes_key_check(aes_key); if (rc) goto ret; if (aes_ecb->aes_key == aes_key) { DEBUG("aes-ecb context at %p: key at %p already set", aes_ecb, aes_key); rc = 0; /* nothing to do */ goto ret; } aes_key->refcount++; DEBUG("aes key at %p: refcount %llu", aes_key, aes_key->refcount); if (aes_ecb->key_set) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-ecb context at %p: key unset", aes_ecb); __aes_ecb_reset(aes_ecb); } /* Set new key. */ assert(!aes_ecb->key_set); DEBUG("aes-ecb context at %p: key at %p set", aes_ecb, aes_key); memcpy(aes_ecb->param.protkey, aes_key->prot.protkey, sizeof(aes_ecb->param.protkey)); aes_ecb->fc = CPACF_KM_ENCRYPTED_AES_128 + (aes_key->keysize - 128) / 64; aes_ecb->aes_key = aes_key; aes_ecb->key_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_ecb_encrypt(struct zpc_aes_ecb *aes_ecb, u8 * c, const u8 * m, size_t mlen) { struct cpacf_km_aes_param *param; struct pkey_protkey *protkey; unsigned long flags = 0; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_ecb) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_ecb == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((mlen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if ((mlen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (mlen % 16 != 0) { rc = ZPC_ERROR_MLEN; } if (!aes_ecb->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_ecb->aes_key->prot; param = &aes_ecb->param; for (;;) { rc = __aes_ecb_crypt(aes_ecb, c, m, mlen, flags); if (rc == 0) { break; } else { if (aes_ecb->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_ecb-> aes_key->lock); assert(rv == 0); DEBUG ("aes-ecb context at %p: re-derive protected key from %s secure key from aes key at %p", aes_ecb, i == 0 ? "current" : "old", aes_ecb->aes_key); rc = aes_key_sec2prot(aes_ecb->aes_key, i); memcpy(param->protkey, protkey->protkey, sizeof(param->protkey)); rv = pthread_mutex_unlock(&aes_ecb-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_ecb_decrypt(struct zpc_aes_ecb *aes_ecb, u8 * m, const u8 * c, size_t clen) { struct cpacf_km_aes_param *param; struct pkey_protkey *protkey; unsigned long flags = CPACF_M; /* decrypt */ int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_ecb) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_ecb == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((clen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if ((clen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (clen % 16 != 0) { rc = ZPC_ERROR_CLEN; goto ret; } if (!aes_ecb->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_ecb->aes_key->prot; param = &aes_ecb->param; for (;;) { rc = __aes_ecb_crypt(aes_ecb, m, c, clen, flags); if (rc == 0) { break; } else { if (aes_ecb->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_ecb-> aes_key->lock); assert(rv == 0); DEBUG ("aes-ecb context at %p: re-derive protected key from %s secure key from aes key at %p", aes_ecb, i == 0 ? "current" : "old", aes_ecb->aes_key); rc = aes_key_sec2prot(aes_ecb->aes_key, i); memcpy(param->protkey, protkey->protkey, sizeof(param->protkey)); rv = pthread_mutex_unlock(&aes_ecb-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } void zpc_aes_ecb_free(struct zpc_aes_ecb **aes_ecb) { if (aes_ecb == NULL) return; if (*aes_ecb == NULL) return; if ((*aes_ecb)->key_set) { /* Decrease aes_key's refcount. */ zpc_aes_key_free(&(*aes_ecb)->aes_key); (*aes_ecb)->key_set = 0; } __aes_ecb_reset(*aes_ecb); free(*aes_ecb); *aes_ecb = NULL; DEBUG("return"); } static int __aes_ecb_crypt(struct zpc_aes_ecb *aes_ecb, u8 * out, const u8 * in, size_t inlen, unsigned long flags) { struct cpacf_km_aes_param *param; int rc, cc; param = &aes_ecb->param; cc = cpacf_km(aes_ecb->fc | flags, param, out, in, inlen); assert(cc == 0 || cc == 1 || cc == 2); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto err; } rc = 0; err: return rc; } static void __aes_ecb_reset(struct zpc_aes_ecb *aes_ecb) { assert(aes_ecb != NULL); memset(&aes_ecb->param, 0, sizeof(aes_ecb->param)); if (aes_ecb->aes_key != NULL) zpc_aes_key_free(&aes_ecb->aes_key); aes_ecb->key_set = 0; aes_ecb->fc = 0; } libzpc-1.0.0/src/aes_ecb_local.h000066400000000000000000000007121413160260300164620ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef AES_ECB_LOCAL_H # define AES_ECB_LOCAL_H # include "zpc/aes_key.h" # include "misc.h" # include "cpacf.h" /* * Internal aes_ecb interface. */ struct zpc_aes_ecb { struct cpacf_km_aes_param param; struct zpc_aes_key *aes_key; unsigned int fc; int key_set; }; #endif libzpc-1.0.0/src/aes_gcm.c000066400000000000000000000334421413160260300153260ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include "zpc/aes_gcm.h" #include "zpc/error.h" #include "aes_gcm_local.h" #include "aes_key_local.h" #include "cpacf.h" #include "globals.h" #include "misc.h" #include "debug.h" #include "zkey/pkey.h" #include #include #include #include #include static int __aes_gcm_set_iv(struct zpc_aes_gcm *, const u8 *, size_t); static int __aes_gcm_crypt(struct zpc_aes_gcm *, u8 *, u8 *, size_t, const u8 *, size_t, const u8 *, size_t, unsigned long); static void __aes_gcm_reset(struct zpc_aes_gcm *); static void __aes_gcm_reset_iv(struct zpc_aes_gcm *); int zpc_aes_gcm_alloc(struct zpc_aes_gcm **aes_gcm) { struct zpc_aes_gcm *new_aes_gcm = NULL; int rc; if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_gcm) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_gcm == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } new_aes_gcm = calloc(1, sizeof(*new_aes_gcm)); if (new_aes_gcm == NULL) { rc = ZPC_ERROR_MALLOC; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } DEBUG("aes-gcm context at %p: allocated", new_aes_gcm); *aes_gcm = new_aes_gcm; rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_gcm_set_key(struct zpc_aes_gcm *aes_gcm, struct zpc_aes_key *aes_key) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_gcm) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_gcm == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-gcm context at %p: key unset", aes_gcm); __aes_gcm_reset(aes_gcm); rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); rc = aes_key_check(aes_key); if (rc) goto ret; if (aes_gcm->aes_key == aes_key) { DEBUG("aes-gcm context at %p: key at %p already set", aes_gcm, aes_key); rc = 0; /* nothing to do */ goto ret; } aes_key->refcount++; DEBUG("aes key at %p: refcount %llu", aes_key, aes_key->refcount); if (aes_gcm->key_set) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-gcm context at %p: key unset", aes_gcm); __aes_gcm_reset(aes_gcm); } /* Set new key. */ assert(!aes_gcm->key_set); DEBUG("aes-gcm context at %p: key at %p set, iv unset", aes_gcm, aes_key); memcpy(aes_gcm->param.protkey, aes_key->prot.protkey, sizeof(aes_gcm->param.protkey)); aes_gcm->fc = CPACF_KMA_GCM_ENCRYPTED_AES_128 + (aes_key->keysize - 128) / 64; aes_gcm->aes_key = aes_key; aes_gcm->key_set = 1; __aes_gcm_reset_iv(aes_gcm); aes_gcm->iv_set = 0; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_gcm_set_iv(struct zpc_aes_gcm *aes_gcm, const u8 * iv, size_t ivlen) { struct cpacf_kma_gcm_aes_param *param; struct pkey_protkey *protkey; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_gcm) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_gcm == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if (iv == NULL) { /* Unset iv */ DEBUG("aes-gcm context at %p: iv unset", aes_gcm); __aes_gcm_reset_iv(aes_gcm); aes_gcm->iv_set = 0; rc = 0; goto ret; } /* 1 <= iv bit-length <= 2^64 - 1, iv bit-length % 8 == 0 */ if (ivlen < 1 || ivlen > SIZE_MAX - 16) { rc = ZPC_ERROR_IVSIZE; goto ret; } if (aes_gcm->key_set != 1) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_gcm->aes_key->prot; param = &aes_gcm->param; for (;;) { rc = __aes_gcm_set_iv(aes_gcm, iv, ivlen); if (rc == 0) { break; } else { if (aes_gcm->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_gcm-> aes_key->lock); assert(rv == 0); DEBUG ("aes-gcm context at %p: re-derive protected key from %s secure key from aes key at %p", aes_gcm, i == 0 ? "current" : "old", aes_gcm->aes_key); rc = aes_key_sec2prot(aes_gcm->aes_key, i); memcpy(param->protkey, protkey->protkey, sizeof(param->protkey)); rv = pthread_mutex_unlock(&aes_gcm-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } if (rc) goto ret; DEBUG("aes-gcm context at %p: iv set", aes_gcm); aes_gcm->iv_set = 1; ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_gcm_encrypt(struct zpc_aes_gcm *aes_gcm, u8 * c, u8 * tag, size_t taglen, const u8 * aad, size_t aadlen, const u8 * m, size_t mlen) { struct cpacf_kma_gcm_aes_param *param; struct pkey_protkey *protkey; unsigned long flags = 0; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_gcm) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_gcm == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((mlen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } /* Valid tag bit-lengths: 128, 120, 112, 104, 96, 64, 32. */ if (taglen > 0 && tag == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (taglen > 16 || (taglen > 0 && taglen < 12 && taglen != 8 && taglen != 4)) { rc = ZPC_ERROR_TAGSIZE; goto ret; } /* aad bit-length <= 2^64 - 1, aad bit-length % 8 == 0 */ if (aadlen > 0 && aad == NULL) { rc = ZPC_ERROR_ARG5NULL; goto ret; } if (aadlen > (2ULL << 61) - 1) { rc = ZPC_ERROR_AADLEN; goto ret; } if (aadlen > 0 && aadlen % 16 != 0 && m == NULL && tag == NULL) { rc = ZPC_ERROR_ARG6RANGE; goto ret; } /* m bit-length <= 2^39 - 256, m bit-length % 8 == 0 */ if ((mlen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG7NULL; goto ret; } if (mlen > (2ULL << 36) - 256) { rc = ZPC_ERROR_MLEN; goto ret; } if (mlen > 0 && mlen % 16 != 0 && tag == NULL) { rc = ZPC_ERROR_ARG8RANGE; goto ret; } if (!aes_gcm->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_gcm->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } if ((m != NULL && c != NULL) || tag != NULL) { flags |= CPACF_KMA_LAAD; if (tag != NULL) flags |= CPACF_KMA_LPC; } aes_gcm->param.taadl += (aadlen * 8); aes_gcm->param.tpcl += (mlen * 8); rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_gcm->aes_key->prot; param = &aes_gcm->param; for (;;) { rc = __aes_gcm_crypt(aes_gcm, c, tag, taglen, aad, aadlen, m, mlen, flags); if (rc == 0) { break; } else { if (aes_gcm->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_gcm-> aes_key->lock); assert(rv == 0); DEBUG ("aes-gcm context at %p: re-derive protected key from %s secure key from aes key at %p", aes_gcm, i == 0 ? "current" : "old", aes_gcm->aes_key); rc = aes_key_sec2prot(aes_gcm->aes_key, i); memcpy(param->protkey, protkey->protkey, sizeof(param->protkey)); rv = pthread_mutex_unlock(&aes_gcm-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_gcm_decrypt(struct zpc_aes_gcm *aes_gcm, u8 * m, const u8 * tag, size_t taglen, const u8 * aad, size_t aadlen, const u8 * c, size_t clen) { struct cpacf_kma_gcm_aes_param *param; struct pkey_protkey *protkey; unsigned long flags = CPACF_M; /* decrypt */ int rc, rv, i; u8 tmp[16]; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_gcm) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_gcm == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((clen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } /* Valid tag bit-lengths: 128, 120, 112, 104, 96, 64, 32. */ if (taglen > 0 && tag == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (taglen > 16 || (taglen > 0 && taglen < 12 && taglen != 8 && taglen != 4)) { rc = ZPC_ERROR_TAGSIZE; goto ret; } /* aad bit-length <= 2^64 - 1, aad bit-length % 8 == 0 */ if (aadlen > 0 && aad == NULL) { rc = ZPC_ERROR_ARG5NULL; goto ret; } if (aadlen > (2ULL << 61) - 1) { rc = ZPC_ERROR_AADLEN; goto ret; } if (aadlen > 0 && aadlen % 16 != 0 && c == NULL && tag == NULL) { rc = ZPC_ERROR_ARG6RANGE; goto ret; } /* c bit-length <= 2^39 - 256, c bit-length % 8 == 0 */ if ((clen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG7NULL; goto ret; } if (clen > (2ULL << 36) - 256) { rc = ZPC_ERROR_CLEN; goto ret; } if (clen > 0 && clen % 16 != 0 && tag == NULL) { rc = ZPC_ERROR_ARG8RANGE; goto ret; } if (!aes_gcm->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_gcm->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } if ((m != NULL && c != NULL) || tag != NULL) { flags |= CPACF_KMA_LAAD; if (tag != NULL) flags |= CPACF_KMA_LPC; } aes_gcm->param.taadl += (aadlen * 8); aes_gcm->param.tpcl += (clen * 8); rc = -1; for (i = 0; i < 2 && (rc != 0 && rc != ZPC_ERROR_TAGMISMATCH); i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_gcm->aes_key->prot; param = &aes_gcm->param; for (;;) { rc = __aes_gcm_crypt(aes_gcm, m, tmp, sizeof(tmp), aad, aadlen, c, clen, flags); if (rc == 0) { rc = memcmp_consttime(tmp, tag, taglen); if (rc) rc = ZPC_ERROR_TAGMISMATCH; break; } else { if (aes_gcm->aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock(&aes_gcm-> aes_key->lock); assert(rv == 0); DEBUG ("aes-gcm context at %p: re-derive protected key from %s secure key from aes key at %p", aes_gcm, i == 0 ? "current" : "old", aes_gcm->aes_key); rc = aes_key_sec2prot(aes_gcm->aes_key, i); memcpy(param->protkey, protkey->protkey, sizeof(param->protkey)); rv = pthread_mutex_unlock(&aes_gcm-> aes_key->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } void zpc_aes_gcm_free(struct zpc_aes_gcm **aes_gcm) { if (aes_gcm == NULL) return; if (*aes_gcm == NULL) return; if ((*aes_gcm)->key_set) { /* Decrease aes_key's refcount. */ zpc_aes_key_free(&(*aes_gcm)->aes_key); (*aes_gcm)->key_set = 0; __aes_gcm_reset_iv(*aes_gcm); (*aes_gcm)->iv_set = 0; } __aes_gcm_reset(*aes_gcm); free(*aes_gcm); *aes_gcm = NULL; DEBUG("return"); } static int __aes_gcm_set_iv(struct zpc_aes_gcm *aes_gcm, const u8 * iv, size_t ivlen) { struct cpacf_kma_gcm_aes_param *param; size_t ivpadlen; u64 *ivpad = NULL; int rc, cc; assert(aes_gcm != NULL); assert(iv != NULL); assert(ivlen <= SIZE_MAX - 16); param = &aes_gcm->param; memset(param->reserved, 0, sizeof(param->reserved)); memset(param->t, 0, sizeof(param->t)); param->taadl = 0; param->tpcl = 0; if (ivlen == 12) { memcpy(param->j0, iv, ivlen); param->j0[12] = 0; param->j0[13] = 0; param->j0[14] = 0; param->j0[15] = 1; param->cv = 1; } else { ivpadlen = (ivlen + 15) / 16 * 16 + 16; ivpad = calloc(1, ivpadlen); if (ivpad == NULL) return ZPC_ERROR_MALLOC; memcpy(ivpad, iv, ivlen); ivpad[ivpadlen / 8 - 1] = ivlen * 8; memset(param->j0, 0, sizeof(param->j0)); cc = cpacf_kma(aes_gcm->fc, param, NULL, (u8 *) ivpad, ivpadlen, NULL, 0); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } aes_gcm->fc |= CPACF_KMA_HS; memcpy(¶m->cv, param->t + 12, sizeof(param->cv)); memcpy(param->j0, param->t, sizeof(param->j0)); memset(param->t, 0, sizeof(param->t)); } rc = 0; ret: free(ivpad); return rc; } static int __aes_gcm_crypt(struct zpc_aes_gcm *aes_gcm, u8 * out, u8 * tag, size_t taglen, const u8 * aad, size_t aadlen, const u8 * in, size_t inlen, unsigned long flags) { struct cpacf_kma_gcm_aes_param *param; int rc, cc; param = &aes_gcm->param; cc = cpacf_kma(aes_gcm->fc | flags, param, out, aad, aadlen, in, inlen); assert(cc == 0 || cc == 1 || cc == 2); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto err; } aes_gcm->fc |= CPACF_KMA_HS; memcpy(tag, param->t, taglen); rc = 0; err: return rc; } static void __aes_gcm_reset(struct zpc_aes_gcm *aes_gcm) { assert(aes_gcm != NULL); memset(&aes_gcm->param, 0, sizeof(aes_gcm->param)); __aes_gcm_reset_iv(aes_gcm); aes_gcm->iv_set = 0; if (aes_gcm->aes_key != NULL) zpc_aes_key_free(&aes_gcm->aes_key); aes_gcm->key_set = 0; aes_gcm->fc = 0; } static void __aes_gcm_reset_iv(struct zpc_aes_gcm *aes_gcm) { assert(aes_gcm != NULL); memset(aes_gcm->param.reserved, 0, sizeof(aes_gcm->param.reserved)); memset(aes_gcm->param.t, 0, sizeof(aes_gcm->param.t)); memset(aes_gcm->param.j0, 0, sizeof(aes_gcm->param.j0)); aes_gcm->param.cv = 0; aes_gcm->param.taadl = 0; aes_gcm->param.tpcl = 0; aes_gcm->fc &= ~(CPACF_KMA_LAAD | CPACF_KMA_LPC); aes_gcm->iv_set = 0; } libzpc-1.0.0/src/aes_gcm_local.h000066400000000000000000000007341413160260300165030ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef AES_GCM_LOCAL_H # define AES_GCM_LOCAL_H # include "zpc/aes_key.h" # include "misc.h" # include "cpacf.h" /* * Internal aes_gcm interface. */ struct zpc_aes_gcm { struct cpacf_kma_gcm_aes_param param; struct zpc_aes_key *aes_key; unsigned int fc; int key_set; int iv_set; }; #endif libzpc-1.0.0/src/aes_key.c000066400000000000000000000524461413160260300153550ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include "zpc/aes_key.h" #include "zpc/error.h" #include "aes_key_local.h" #include "globals.h" #include "debug.h" #include "misc.h" #include "zkey/pkey.h" #include #include #include #include #include #include #include static int __aes_key_alloc_apqns_from_mkvp(struct pkey_apqn **, size_t *, const unsigned char[], int); static void __aes_key_reset(struct zpc_aes_key *); int zpc_aes_key_alloc(struct zpc_aes_key **aes_key) { pthread_mutexattr_t attr; struct zpc_aes_key *new_aes_key = NULL; int rc, rv, attr_init = 0; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } new_aes_key = calloc(1, sizeof(*new_aes_key)); if (new_aes_key == NULL) { rc = ZPC_ERROR_MALLOC; goto ret; } rc = pthread_mutexattr_init(&attr); if (rc) { rc = ZPC_ERROR_MALLOC; goto ret; } attr_init = 1; rv = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); assert(rv == 0); rc = pthread_mutex_init(&new_aes_key->lock, &attr); if (rc) { rc = ZPC_ERROR_INITLOCK; goto ret; } new_aes_key->refcount = 1; DEBUG("aes key at %p: refcount %llu", new_aes_key, new_aes_key->refcount); *aes_key = new_aes_key; rc = 0; ret: if (attr_init == 1) { rv = pthread_mutexattr_destroy(&attr); assert(rv == 0); } if (rc) free(new_aes_key); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_set_size(struct zpc_aes_key *aes_key, int keysize) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } switch (keysize) { case 128: /* fall-through */ case 192: /* fall-through */ case 256: break; default: rc = ZPC_ERROR_KEYSIZE; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } if (aes_key->key_set == 1 && aes_key->keysize != keysize) { /* Unset key if it does not match the new keysize. */ DEBUG("aes key at %p: key unset", aes_key); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); memset(&aes_key->old, 0, sizeof(aes_key->old)); aes_key->key_set = 0; } DEBUG("aes key at %p: size set to %d", aes_key, keysize); aes_key->keysize = keysize; aes_key->keysize_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_set_type(struct zpc_aes_key *aes_key, int type) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } switch (type) { case ZPC_AES_KEY_TYPE_CCA_DATA: /* fall-through */ case ZPC_AES_KEY_TYPE_CCA_CIPHER: /* fall-through */ case ZPC_AES_KEY_TYPE_EP11: break; default: rc = ZPC_ERROR_KEYTYPE; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } if (aes_key->type_set == 1 && aes_key->type != type && aes_key->mkvp_set == 1) { /* Update mkvp-based apqn choices in case of type change. */ DEBUG("aes key at %p: update apqns to match type %d", aes_key, type); free(aes_key->apqns); aes_key->apqns = NULL; aes_key->napqns = 0; aes_key->apqns_set = 0; rc = __aes_key_alloc_apqns_from_mkvp(&(aes_key->apqns), &(aes_key->napqns), aes_key->mkvp, type); if (rc != 0) goto ret; DEBUG("aes key at %p: %lu apqns set", aes_key, aes_key->napqns); aes_key->apqns_set = 1; } DEBUG("aes key at %p: type set to %d", aes_key, type); aes_key->type = type; aes_key->type_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_set_flags(struct zpc_aes_key *aes_key, unsigned int flags) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } DEBUG("aes key at %p: flags set to %u", aes_key, flags); aes_key->flags = flags; aes_key->flags_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } /* * Associate aes_key to all apqns of the given mkvp. */ int zpc_aes_key_set_mkvp(struct zpc_aes_key *aes_key, const char *mkvp) { u8 mkvpbuf[MAX_MKVPLEN]; size_t mkvpbuflen; int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } if (mkvp == NULL) { DEBUG("aes key at %p: apqns unset", aes_key); free(aes_key->apqns); aes_key->apqns = NULL; aes_key->napqns = 0; aes_key->apqns_set = 0; rc = 0; goto ret; } mkvpbuflen = sizeof(mkvpbuf); if (hexstr2buf(mkvpbuf, &mkvpbuflen, mkvp)) { rc = ZPC_ERROR_PARSE; goto ret; } if (mkvpbuflen != 8 && mkvpbuflen != 16 && mkvpbuflen != 32) { rc = ZPC_ERROR_MKVPLEN; goto ret; } if (aes_key->type_set != 1) { rc = ZPC_ERROR_KEYTYPENOTSET; goto ret; } DEBUG("aes key at %p: apqns unset", aes_key); free(aes_key->apqns); aes_key->apqns = NULL; aes_key->napqns = 0; aes_key->apqns_set = 0; rc = __aes_key_alloc_apqns_from_mkvp(&(aes_key->apqns), &(aes_key->napqns), mkvpbuf, aes_key->type); if (rc != 0) goto ret; DEBUG("aes key at %p: mkvp and %lu apqns set", aes_key, aes_key->napqns); memcpy(aes_key->mkvp, mkvpbuf, mkvpbuflen); aes_key->apqns_set = 1; aes_key->mkvp_set = 1; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } /* * Associate aes_key to a list NULL terminated list of apqns. */ int zpc_aes_key_set_apqns(struct zpc_aes_key *aes_key, const char *apqns[]) { unsigned int card, domain; size_t i, napqns; int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (apqns == NULL) { DEBUG("aes key at %p: apqns unset", aes_key); free(aes_key->apqns); aes_key->apqns = NULL; aes_key->napqns = 0; aes_key->apqns_set = 0; rc = 0; goto ret; } for (napqns = 0; apqns[napqns] != NULL; napqns++); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } DEBUG("aes key at %p: apqns unset", aes_key); free(aes_key->apqns); aes_key->apqns = NULL; aes_key->napqns = 0; aes_key->apqns_set = 0; DEBUG("aes key at %p: mkvp unset", aes_key); memset(aes_key->mkvp, 0, sizeof(aes_key->mkvp)); aes_key->mkvplen = 0; aes_key->mkvp_set = 0; if (napqns == 0) { rc = 0; /* nothing to do */ goto ret; } aes_key->apqns = calloc(napqns, sizeof(*(aes_key->apqns))); if (aes_key->apqns == NULL) return ZPC_ERROR_MALLOC; for (i = 0; i < napqns; i++) { rc = sscanf(apqns[i], " %x.%x ", &card, &domain); if (rc != 2) { rc = ZPC_ERROR_PARSE; goto ret; } aes_key->apqns[i].card = card; aes_key->apqns[i].domain = domain; } DEBUG("aes key at %p: %lu apqns set", aes_key, aes_key->napqns); aes_key->napqns = napqns; aes_key->apqns_set = 1; rc = 0; ret: if (rc != 0) { free(aes_key->apqns); aes_key->napqns = 0; } rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_import_clear(struct zpc_aes_key *aes_key, const unsigned char *key) { struct pkey_clr2seck2 clr2seck2; unsigned int flags; int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (key == NULL) { rc = ZPC_ERROR_ARG2NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } if (aes_key->apqns_set != 1) { rc = ZPC_ERROR_APQNSNOTSET; goto ret; } if (aes_key->keysize_set != 1) { rc = ZPC_ERROR_KEYSIZENOTSET; goto ret; } if (aes_key->type_set != 1) { rc = ZPC_ERROR_KEYTYPENOTSET; goto ret; } flags = aes_key->flags_set == 1 ? aes_key->flags : 0; memset(&aes_key->cur, 0, sizeof(aes_key->cur)); memset(&aes_key->old, 0, sizeof(aes_key->old)); aes_key->key_set = 0; memset(&clr2seck2, 0, sizeof(clr2seck2)); clr2seck2.apqns = aes_key->apqns; clr2seck2.apqn_entries = aes_key->napqns; clr2seck2.type = aes_key->type; clr2seck2.size = aes_key->keysize; clr2seck2.keygenflags = flags; memcpy(&clr2seck2.clrkey, key, aes_key->keysize / 8); clr2seck2.key = aes_key->cur.sec; clr2seck2.keylen = sizeof(aes_key->cur.sec); rc = ioctl(pkeyfd, PKEY_CLR2SECK2, &clr2seck2); if (rc != 0) { rc = ZPC_ERROR_IOCTLCLR2SECK2; goto ret; } aes_key->cur.seclen = clr2seck2.keylen; rc = aes_key_sec2prot(aes_key, AES_KEY_SEC_CUR); if (rc) { goto ret; } DEBUG("aes key at %p: key set", aes_key); aes_key->key_set = 1; rc = 0; ret: if (rc != 0) memset(&aes_key->cur, 0, sizeof(aes_key->cur)); rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); memzero_secure(&clr2seck2.clrkey, sizeof(clr2seck2.clrkey)); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_export(struct zpc_aes_key *aes_key, unsigned char *buf, size_t *buflen) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (buflen == NULL) { rc = ZPC_ERROR_ARG3NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } rc = aes_key_check(aes_key); if (rc) goto ret; if (buf == NULL) { *buflen = aes_key->cur.seclen; rc = 0; goto ret; } if (*buflen < aes_key->cur.seclen) { *buflen = aes_key->cur.seclen; rc = ZPC_ERROR_SMALLOUTBUF; goto ret; } *buflen = aes_key->cur.seclen; memcpy(buf, aes_key->cur.sec, *buflen); rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_import(struct zpc_aes_key *aes_key, const unsigned char *buf, size_t buflen) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { return ZPC_ERROR_DEVPKEY; } if (aes_key == NULL) { return ZPC_ERROR_ARG1NULL; } if (buf == NULL) { return ZPC_ERROR_ARG2NULL; } if (buflen < MIN_SECURE_KEY_SIZE || buflen > MAX_SECURE_KEY_SIZE) { return ZPC_ERROR_ARG3RANGE; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } if (aes_key->keysize_set != 1) { rc = ZPC_ERROR_KEYSIZENOTSET; goto ret; } if (aes_key->type_set != 1) { rc = ZPC_ERROR_KEYTYPENOTSET; goto ret; } memset(aes_key->cur.sec, 0, sizeof(aes_key->cur.sec)); memcpy(aes_key->cur.sec, buf, buflen); aes_key->cur.seclen = buflen; aes_key->key_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_generate(struct zpc_aes_key *aes_key) { struct pkey_genseck2 genseck2; struct pkey_genprotk genprotk; unsigned int flags; int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->refcount != 1) { rc = ZPC_ERROR_OBJINUSE; goto ret; } if (aes_key->keysize_set != 1) { rc = ZPC_ERROR_KEYSIZENOTSET; goto ret; } if (aes_key->apqns_set != 1) { /* Generate random protected key only. */ memset(&genprotk, 0, sizeof(genprotk)); switch (aes_key->keysize) { case 128: genprotk.keytype = PKEY_KEYTYPE_AES_128; break; case 192: genprotk.keytype = PKEY_KEYTYPE_AES_192; break; case 256: genprotk.keytype = PKEY_KEYTYPE_AES_256; break; default: rc = ZPC_ERROR_KEYSIZE; goto ret; break; } rc = ioctl(pkeyfd, PKEY_GENPROTK, &genprotk); if (rc != 0) { rc = ZPC_ERROR_IOCTLGENPROTK; goto ret; } DEBUG("aes key at %p: key set to generated protected key", aes_key); memcpy(&aes_key->prot, &genprotk.protkey, sizeof(aes_key->prot)); aes_key->rand_protk = 1; aes_key->key_set = 1; rc = 0; goto ret; } if (aes_key->type_set != 1) { rc = ZPC_ERROR_KEYTYPENOTSET; goto ret; } flags = aes_key->flags_set == 1 ? aes_key->flags : 0; memset(&aes_key->cur, 0, sizeof(aes_key->cur)); memset(&aes_key->old, 0, sizeof(aes_key->old)); aes_key->key_set = 0; memset(&genseck2, 0, sizeof(genseck2)); genseck2.apqns = aes_key->apqns; genseck2.apqn_entries = aes_key->napqns; genseck2.type = aes_key->type; genseck2.size = aes_key->keysize; genseck2.keygenflags = flags; genseck2.key = aes_key->cur.sec; genseck2.keylen = sizeof(aes_key->cur.sec); rc = ioctl(pkeyfd, PKEY_GENSECK2, &genseck2); if (rc != 0) { rc = ZPC_ERROR_IOCTLGENSECK2; goto ret; } aes_key->cur.seclen = genseck2.keylen; rc = aes_key_sec2prot(aes_key, AES_KEY_SEC_CUR); if (rc) goto ret; DEBUG("aes key at %p: key set to generated secure key", aes_key); aes_key->key_set = 1; rc = 0; ret: if (rc != 0) memset(&aes_key->cur, 0, sizeof(aes_key->cur)); rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_key_reencipher(struct zpc_aes_key *aes_key, int method) { struct aes_key reenc; unsigned int seckeylen; target_t target; int rv, rc = ZPC_ERROR_APQNSNOTSET; size_t i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } rv = pthread_mutex_lock(&aes_key->lock); assert(rv == 0); if (aes_key->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (aes_key->key_set == 0) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (aes_key->keysize_set == 0) { rc = ZPC_ERROR_KEYSIZENOTSET; goto ret; } if (aes_key->type_set == 0) { rc = ZPC_ERROR_KEYTYPENOTSET; goto ret; } if (aes_key->apqns_set == 0 || aes_key->napqns == 0) { rc = ZPC_ERROR_APQNSNOTSET; goto ret; } memcpy(&reenc, &aes_key->cur, sizeof(reenc)); switch (aes_key->type) { case ZPC_AES_KEY_TYPE_CCA_DATA: /* fall-through */ case ZPC_AES_KEY_TYPE_CCA_CIPHER: /* fall-through */ seckeylen = aes_key->type == ZPC_AES_KEY_TYPE_CCA_DATA ? AESDATA_KEY_SIZE : AESCIPHER_KEY_SIZE; rv = pthread_mutex_lock(&ccalock); assert(rv == 0); for (i = 0; i < aes_key->napqns; i++) { rc = select_cca_adapter(&cca, aes_key->apqns[i].card, aes_key->apqns[i].domain, true); if (rc) continue; rc = key_token_change(&cca, reenc.sec, seckeylen, method == ZPC_AES_KEY_REENCIPHER_OLD_TO_CURRENT ? METHOD_OLD_TO_CURRENT : METHOD_CURRENT_TO_NEW, true); if (rc == 0) break; } rv = pthread_mutex_unlock(&ccalock); assert(rv == 0); break; case ZPC_AES_KEY_TYPE_EP11: if (method != ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW) { rc = ZPC_ERROR_NOTSUP; goto ret; } rv = pthread_mutex_lock(&ep11lock); assert(rv == 0); for (i = 0; i < aes_key->napqns; i++) { rc = get_ep11_target_for_apqn(&ep11, aes_key->apqns[i].card, aes_key->apqns[i].domain, &target, true); if (rc) continue; rc = reencipher_ep11_key(&ep11, target, aes_key->apqns[i].card, aes_key->apqns[i].domain, reenc.sec, aes_key->cur.seclen, true); free_ep11_target_for_apqn(&ep11, target); if (rc == 0) break; } rv = pthread_mutex_unlock(&ep11lock); assert(rv == 0); break; default: rc = ZPC_ERROR_KEYTYPE; } if (rc) goto ret; memcpy(&aes_key->old, &aes_key->cur, sizeof(aes_key->old)); memcpy(&aes_key->cur, &reenc, sizeof(aes_key->cur)); rc = 0; ret: rv = pthread_mutex_unlock(&aes_key->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } void zpc_aes_key_free(struct zpc_aes_key **aes_key) { int rv, free_obj = 0; UNUSED(rv); if (aes_key == NULL) return; if (*aes_key == NULL) return; rv = pthread_mutex_lock(&(*aes_key)->lock); assert(rv == 0); if ((*aes_key)->refcount == 0) goto ret; (*aes_key)->refcount--; DEBUG("aes key at %p: refcount %llu", *aes_key, (*aes_key)->refcount); if ((*aes_key)->refcount == 0) { free_obj = 1; __aes_key_reset(*aes_key); } ret: rv = pthread_mutex_unlock(&(*aes_key)->lock); assert(rv == 0); if (free_obj == 1) { rv = pthread_mutex_destroy(&(*aes_key)->lock); assert(rv == 0); free(*aes_key); } *aes_key = NULL; DEBUG("return"); } /* * Reset everything that was set after allocation. * Caller must hold aes_key's wr lock. */ static void __aes_key_reset(struct zpc_aes_key *aes_key) { assert(aes_key != NULL); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); memset(&aes_key->old, 0, sizeof(aes_key->old)); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); aes_key->key_set = 0; aes_key->keysize = 0; aes_key->keysize_set = 0; aes_key->flags = 0; aes_key->flags_set = 0; aes_key->type = 0; aes_key->type_set = 0; memset(aes_key->mkvp, 0, sizeof(aes_key->mkvp)); aes_key->mkvplen = 0; aes_key->mkvp_set = 0; free(aes_key->apqns); aes_key->apqns = NULL; aes_key->napqns = 0; aes_key->apqns_set = 0; aes_key->rand_protk = 0; aes_key->refcount = 1; } /* * (Re)derive protected key from a secure key. * Caller must hold aes_key's wr lock. */ int aes_key_sec2prot(struct zpc_aes_key *aes_key, enum aes_key_sec sec) { struct pkey_kblob2pkey2 io; struct aes_key *key = NULL; int rc; assert(sec == AES_KEY_SEC_OLD || sec == AES_KEY_SEC_CUR); if (sec == AES_KEY_SEC_CUR) key = &aes_key->cur; else if (sec == AES_KEY_SEC_OLD) key = &aes_key->old; assert(key != NULL); memset(&io, 0, sizeof(io)); io.key = key->sec; io.keylen = key->seclen; io.apqns = aes_key->apqns; io.apqn_entries = aes_key->napqns; rc = ioctl(pkeyfd, PKEY_KBLOB2PROTK2, &io); if (rc != 0) return ZPC_ERROR_IOCTLBLOB2PROTK2; memcpy(&aes_key->prot, &io.protkey, sizeof(aes_key->prot)); return 0; } /* * Returns list of napqns in apqns that match the mkvp and key type. * Caller takes ownership of apqns. * Returns 0 on success. Otherwise, an appropriate ZPC_ERROR is returned. */ static int __aes_key_alloc_apqns_from_mkvp(struct pkey_apqn **apqns, size_t *napqns, const unsigned char mkvp[], int type) { struct pkey_apqns4keytype apqns4keytype; int rc; assert(apqns != NULL); assert(napqns != NULL); assert(mkvp != NULL); *apqns = NULL; *napqns = 0; for (;;) { if (*napqns > 0) { *apqns = calloc(*napqns, sizeof(**apqns)); if (*apqns == NULL) { rc = ZPC_ERROR_MALLOC; goto ret; } } memset(&apqns4keytype, 0, sizeof(apqns4keytype)); apqns4keytype.type = type; memcpy(apqns4keytype.cur_mkvp, mkvp, sizeof(apqns4keytype.cur_mkvp)); memcpy(apqns4keytype.alt_mkvp, mkvp, sizeof(apqns4keytype.alt_mkvp)); apqns4keytype.flags = PKEY_FLAGS_MATCH_CUR_MKVP; apqns4keytype.apqns = *apqns; apqns4keytype.apqn_entries = *napqns; rc = ioctl(pkeyfd, PKEY_APQNS4KT, &apqns4keytype); if (rc && (*napqns == 0 || (*napqns > 0 && rc != ENOSPC))) { rc = ZPC_ERROR_IOCTLAPQNS4KT; goto ret; } else if (rc == 0 && apqns4keytype.apqn_entries == 0) { rc = ZPC_ERROR_APQNNOTFOUND; goto ret; } else if (rc == 0 && *napqns > 0) { break; } free(*apqns); *apqns = NULL; *napqns = apqns4keytype.apqn_entries; } rc = 0; ret: return rc; } int aes_key_check(const struct zpc_aes_key *aes_key) { if (aes_key->key_set != 1) return ZPC_ERROR_KEYNOTSET; if (aes_key->keysize_set != 1) return ZPC_ERROR_KEYSIZENOTSET; /* Random protected keys have no type. */ if (aes_key->rand_protk == 0 && aes_key->type_set != 1) return ZPC_ERROR_KEYTYPENOTSET; return 0; } libzpc-1.0.0/src/aes_key_local.h000066400000000000000000000025151413160260300165240ustar00rootroot00000000000000#ifndef AES_KEY_LOCAL_H # define AES_KEY_LOCAL_H /* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ # include "misc.h" # include "zpc/aes_key.h" # include # include /* * Internal aes_key interface. */ /* Maximum binary MKVP byte-length. */ # define MAX_MKVPLEN 32 /* Maximum size of secure key blob. */ # define MAX_AESKEYBLOBSIZE 512 enum aes_key_sec { AES_KEY_SEC_CUR = 0, AES_KEY_SEC_OLD = 1, }; struct aes_key { unsigned char sec[MAX_AESKEYBLOBSIZE]; size_t seclen; /* byte-length of secure key blob */ }; struct zpc_aes_key { struct aes_key cur; /* old secure key is needed when */ struct aes_key old; /* current is not usable yet */ struct pkey_protkey prot; /* protected key derived from sec */ int key_set; int keysize; int keysize_set; unsigned int flags; int flags_set; int type; int type_set; u8 mkvp[MAX_MKVPLEN]; size_t mkvplen; /* byte-length of mkvp */ int mkvp_set; struct pkey_apqn *apqns; size_t napqns; /* elements in apqns */ int apqns_set; int rand_protk; unsigned long long refcount; pthread_mutex_t lock; }; int aes_key_sec2prot(struct zpc_aes_key *, enum aes_key_sec sec); int aes_key_check(const struct zpc_aes_key *); #endif libzpc-1.0.0/src/aes_xts.c000066400000000000000000000334471413160260300154030ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include "zpc/aes_xts.h" #include "zpc/error.h" #include "aes_xts_local.h" #include "aes_key_local.h" #include "cpacf.h" #include "globals.h" #include "misc.h" #include "debug.h" #include "zkey/pkey.h" #include #include #include #include #include static int __aes_xts_set_iv(struct zpc_aes_xts *, const u8 *); static int __aes_xts_crypt(struct zpc_aes_xts *, u8 *, const u8 *, size_t, unsigned long); static void __aes_xts_reset(struct zpc_aes_xts *); static void __aes_xts_reset_iv(struct zpc_aes_xts *); int zpc_aes_xts_alloc(struct zpc_aes_xts **aes_xts) { struct zpc_aes_xts *new_aes_xts = NULL; int rc; if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_xts) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_xts == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } new_aes_xts = calloc(1, sizeof(*new_aes_xts)); if (new_aes_xts == NULL) { rc = ZPC_ERROR_MALLOC; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } DEBUG("aes-xts context at %p: allocated", new_aes_xts); *aes_xts = new_aes_xts; rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_xts_set_key(struct zpc_aes_xts *aes_xts, struct zpc_aes_key *aes_key1, struct zpc_aes_key *aes_key2) { int rc, rv; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (!hwcaps.aes_xts) { rc = ZPC_ERROR_HWCAPS; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_xts == NULL) { rc = ZPC_ERROR_ARG1NULL; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key1 == NULL || aes_key2 == NULL) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-xts context at %p: key unset", aes_xts); __aes_xts_reset(aes_xts); rc = 0; DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } if (aes_key1 == aes_key2) { rc = ZPC_ERROR_KEYSEQUAL; goto ret; } rv = pthread_mutex_lock(&aes_key1->lock); assert(rv == 0); rv = pthread_mutex_lock(&aes_key2->lock); assert(rv == 0); rc = aes_key_check(aes_key1); if (rc) goto ret; rc = aes_key_check(aes_key2); if (rc) goto ret; if (aes_key1->keysize != aes_key2->keysize) { rc = ZPC_ERROR_KEYSIZE; goto ret; } if (aes_key1->keysize != 128 && aes_key1->keysize != 256) { rc = ZPC_ERROR_KEYSIZE; goto ret; } if (aes_xts->aes_key1 == aes_key1 && aes_xts->aes_key2 == aes_key2) { DEBUG("aes-xts context at %p: keys at %p and %p already set", aes_xts, aes_key1, aes_key2); rc = 0; /* nothing to do */ goto ret; } aes_key1->refcount++; DEBUG("aes key at %p: refcount %llu", aes_key1, aes_key1->refcount); aes_key2->refcount++; DEBUG("aes key at %p: refcount %llu", aes_key2, aes_key2->refcount); if (aes_xts->key_set) { /* If another key is already set, unset it and decrease * refcount. */ DEBUG("aes-xts context at %p: key unset", aes_xts); __aes_xts_reset(aes_xts); } /* Set new key. */ assert(!aes_xts->key_set); DEBUG("aes-xts context at %p: keys at %p and %p set", aes_xts, aes_key1, aes_key2); memcpy(aes_xts->param_km, aes_key1->prot.protkey, AES_XTS_PROTKEYLEN(aes_key1->keysize)); memcpy(aes_xts->param_pcc, aes_key2->prot.protkey, AES_XTS_PROTKEYLEN(aes_key2->keysize)); /* PCC uses the same function codes for 128 resp. 256 bit keys. */ aes_xts->fc = CPACF_KM_XTS_ENCRYPTED_AES_128 + (aes_key1->keysize - 128) / 64; aes_xts->aes_key1 = aes_key1; aes_xts->aes_key2 = aes_key2; aes_xts->key_set = 1; rc = 0; ret: rv = pthread_mutex_unlock(&aes_key1->lock); assert(rv == 0); rv = pthread_mutex_unlock(&aes_key2->lock); assert(rv == 0); DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_xts_set_iv(struct zpc_aes_xts *aes_xts, const u8 * iv) { struct pkey_protkey *protkey; int rc, rv, i; u8 *param; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_xts) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_xts == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if (iv == NULL) { /* Unset iv */ DEBUG("aes-xts context at %p: iv unset", aes_xts); __aes_xts_reset_iv(aes_xts); aes_xts->iv_set = 0; rc = 0; goto ret; } if (aes_xts->key_set != 1) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_xts->aes_key2->prot; param = aes_xts->param_pcc; for (;;) { rc = __aes_xts_set_iv(aes_xts, iv); if (rc == 0) { break; } else { if (aes_xts->aes_key2->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock (&aes_xts->aes_key2->lock); assert(rv == 0); DEBUG ("aes-xts context at %p: re-derive protected key from %s secure key from aes key at %p", aes_xts, i == 0 ? "current" : "old", aes_xts->aes_key2); rc = aes_key_sec2prot(aes_xts->aes_key2, i); memcpy(param, protkey->protkey, AES_XTS_PROTKEYLEN (aes_xts->aes_key2->keysize)); rv = pthread_mutex_unlock (&aes_xts->aes_key2->lock); assert(rv == 0); } if (rc) break; } } } if (rc) goto ret; DEBUG("aes-xts context at %p: iv set", aes_xts); aes_xts->iv_set = 1; ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_xts_encrypt(struct zpc_aes_xts *aes_xts, u8 * c, const u8 * m, size_t mlen) { struct pkey_protkey *protkey; unsigned long flags = 0; u8 *param; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_xts) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_xts == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((mlen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if ((mlen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (mlen < 16) { rc = ZPC_ERROR_MLEN; goto ret; } if (!aes_xts->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_xts->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_xts->aes_key1->prot; param = aes_xts->param_km; for (;;) { rc = __aes_xts_crypt(aes_xts, c, m, mlen, flags); if (rc == 0) { break; } else { if (aes_xts->aes_key1->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock (&aes_xts->aes_key1->lock); assert(rv == 0); DEBUG ("aes-xts context at %p: re-derive protected key" " from %s secure key from aes key at %p", aes_xts, i == 0 ? "current" : "old", aes_xts->aes_key1); rc = aes_key_sec2prot(aes_xts->aes_key1, i); memcpy(param, protkey->protkey, AES_XTS_PROTKEYLEN (aes_xts->aes_key1->keysize)); rv = pthread_mutex_unlock (&aes_xts->aes_key1->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } int zpc_aes_xts_decrypt(struct zpc_aes_xts *aes_xts, u8 * m, const u8 * c, size_t clen) { struct pkey_protkey *protkey; unsigned long flags = CPACF_M; /* decrypt */ u8 *param; int rc, rv, i; UNUSED(rv); if (pkeyfd < 0) { rc = ZPC_ERROR_DEVPKEY; goto ret; } if (!hwcaps.aes_xts) { rc = ZPC_ERROR_HWCAPS; goto ret; } if (aes_xts == NULL) { rc = ZPC_ERROR_ARG1NULL; goto ret; } if ((clen > 0 || c != NULL) && m == NULL) { rc = ZPC_ERROR_ARG2NULL; goto ret; } if ((clen > 0 || m != NULL) && c == NULL) { rc = ZPC_ERROR_ARG3NULL; goto ret; } if (clen < 16) { rc = ZPC_ERROR_CLEN; goto ret; } if (!aes_xts->key_set) { rc = ZPC_ERROR_KEYNOTSET; goto ret; } if (!aes_xts->iv_set) { rc = ZPC_ERROR_IVNOTSET; goto ret; } rc = -1; for (i = 0; i < 2 && rc != 0; i++) { assert(i == AES_KEY_SEC_CUR || i == AES_KEY_SEC_OLD); protkey = &aes_xts->aes_key1->prot; param = aes_xts->param_km; for (;;) { rc = __aes_xts_crypt(aes_xts, m, c, clen, flags); if (rc == 0) { break; } else { if (aes_xts->aes_key1->rand_protk) { rc = ZPC_ERROR_PROTKEYONLY; goto ret; } if (rc == ZPC_ERROR_WKVPMISMATCH) { rv = pthread_mutex_lock (&aes_xts->aes_key1->lock); assert(rv == 0); DEBUG ("aes-xts context at %p: re-derive protected key" " from %s secure key from aes key at %p", aes_xts, i == 0 ? "current" : "old", aes_xts->aes_key1); rc = aes_key_sec2prot(aes_xts->aes_key1, i); memcpy(param, protkey->protkey, AES_XTS_PROTKEYLEN (aes_xts->aes_key1->keysize)); rv = pthread_mutex_unlock (&aes_xts->aes_key1->lock); assert(rv == 0); } if (rc) break; } } } ret: DEBUG("return %d (%s)", rc, zpc_error_string(rc)); return rc; } void zpc_aes_xts_free(struct zpc_aes_xts **aes_xts) { if (aes_xts == NULL) return; if (*aes_xts == NULL) return; if ((*aes_xts)->key_set) { /* Decrease aes_key's refcount. */ zpc_aes_key_free(&(*aes_xts)->aes_key1); zpc_aes_key_free(&(*aes_xts)->aes_key2); (*aes_xts)->key_set = 0; __aes_xts_reset_iv(*aes_xts); (*aes_xts)->iv_set = 0; } __aes_xts_reset(*aes_xts); free(*aes_xts); *aes_xts = NULL; DEBUG("return"); } static int __aes_xts_set_iv(struct zpc_aes_xts *aes_xts, const u8 * iv) { int rc, cc, off1, off2; assert(aes_xts != NULL); assert(iv != NULL); assert(aes_xts->aes_key1 != NULL); assert(aes_xts->aes_key2 != NULL); assert(aes_xts->key_set == 1); /* set i */ off1 = AES_XTS_PCC_I(aes_xts->aes_key2->keysize); memcpy(aes_xts->param_pcc + off1, iv, 16); /* zero j, t, xtsparam */ off2 = AES_XTS_PCC_J(aes_xts->aes_key2->keysize); memset(aes_xts->param_pcc + off2, 0, 3 * 16); cc = cpacf_pcc(aes_xts->fc, aes_xts->param_pcc); /* Either incomplete processing or WKaVP mismatch. */ assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } off1 = AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize); off2 = AES_XTS_PCC_XTSPARAM(aes_xts->aes_key2->keysize); memcpy(aes_xts->param_km + off1, aes_xts->param_pcc + off2, 16); rc = 0; ret: return rc; } static int __aes_xts_crypt(struct zpc_aes_xts *aes_xts, u8 * out, const u8 * in, size_t inlen, unsigned long flags) { int rc, cc; size_t rem; u8 tmp[16]; rem = inlen & 0xf; inlen &= ~(size_t)0xf; if (rem == 0) { cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in, inlen); assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } rc = 0; goto ret; } inlen -= 16; if (!(flags & CPACF_M)) { /* ciphertext-stealing (encrypt) */ cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in, inlen + 16); assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } memcpy(tmp, in + inlen + 16, rem); memcpy(tmp + rem, out + inlen + rem, 16 - rem); memcpy(out + inlen + 16, out + inlen, rem); cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + inlen, tmp, 16); assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } } else if ((flags & CPACF_M)) { /* ciphertext-stealing (decrypt) */ u8 xtsparam[16], buf[16]; if (inlen) { cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out, in, inlen); assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } } memcpy(xtsparam, aes_xts->param_km + AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize), 16); cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, buf, in + inlen, 16); assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + inlen, in + inlen, 16); assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } memcpy(tmp, in + inlen + 16, rem); memcpy(tmp + rem, out + inlen + rem, 16 - rem); memcpy(out + inlen + 16, out + inlen, rem); memcpy(aes_xts->param_km + AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize), xtsparam, 16); cc = cpacf_km(aes_xts->fc | flags, aes_xts->param_km, out + inlen, tmp, 16); assert(cc == 0 || cc == 2 || cc == 1); if (cc == 1) { rc = ZPC_ERROR_WKVPMISMATCH; goto ret; } } rc = 0; ret: return rc; } static void __aes_xts_reset(struct zpc_aes_xts *aes_xts) { assert(aes_xts != NULL); memset(aes_xts->param_km, 0, sizeof(aes_xts->param_km)); memset(aes_xts->param_pcc, 0, sizeof(aes_xts->param_pcc)); __aes_xts_reset_iv(aes_xts); aes_xts->iv_set = 0; if (aes_xts->aes_key1 != NULL) zpc_aes_key_free(&aes_xts->aes_key1); if (aes_xts->aes_key2 != NULL) zpc_aes_key_free(&aes_xts->aes_key2); aes_xts->key_set = 0; aes_xts->fc = 0; } static void __aes_xts_reset_iv(struct zpc_aes_xts *aes_xts) { assert(aes_xts != NULL); if (aes_xts->key_set == 1) { assert(aes_xts->aes_key1 != NULL); assert(aes_xts->aes_key2 != NULL); memset(aes_xts->param_km + AES_XTS_KM_XTSPARAM(aes_xts->aes_key1->keysize), 0, 1 * 16); /* zero i, j, t, xtsparam */ memset(aes_xts->param_pcc + AES_XTS_PCC_I(aes_xts->aes_key2->keysize), 0, 4 * 16); } aes_xts->iv_set = 0; } libzpc-1.0.0/src/aes_xts_local.h000066400000000000000000000022441413160260300165510ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef AES_XTS_LOCAL_H # define AES_XTS_LOCAL_H # include "zpc/aes_key.h" # include "misc.h" # include "cpacf.h" /* * Internal aes_xts interface. */ /* compute protected key length [bytes] from key-size [bits] */ # define AES_XTS_PROTKEYLEN(size) (32 + 16 * (size) / 128 ) /* compute offsets [bytes] in PCC param structure from key-size [bits] */ # define AES_XTS_PCC_I(size) AES_XTS_PROTKEYLEN(size) + 0 * 16 # define AES_XTS_PCC_J(size) AES_XTS_PROTKEYLEN(size) + 1 * 16 # define AES_XTS_PCC_T(size) AES_XTS_PROTKEYLEN(size) + 2 * 16 # define AES_XTS_PCC_XTSPARAM(size) AES_XTS_PROTKEYLEN(size) + 3 * 16 /* compute offsets [bytes] in KM param structure from key-size [bits] */ # define AES_XTS_KM_XTSPARAM(size) AES_XTS_PROTKEYLEN(size) + 0 * 16 struct zpc_aes_xts { u8 param_km[sizeof(struct cpacf_km_xts_aes_256_param)]; u8 param_pcc[sizeof(struct cpacf_pcc_xts_aes_256_param)]; struct zpc_aes_key *aes_key1; struct zpc_aes_key *aes_key2; unsigned int fc; int key_set; int iv_set; }; #endif libzpc-1.0.0/src/cpacf.h000066400000000000000000000154141413160260300150100ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef CPACF_H # define CPACF_H # include "misc.h" # define CPACF_M 0x80 /* Modifier bit */ /* KM */ /* Function codes */ # define CPACF_KM_QUERY 0 # define CPACF_KM_ENCRYPTED_AES_128 26 # define CPACF_KM_ENCRYPTED_AES_192 27 # define CPACF_KM_ENCRYPTED_AES_256 28 # define CPACF_KM_XTS_ENCRYPTED_AES_128 58 # define CPACF_KM_XTS_ENCRYPTED_AES_256 60 struct cpacf_km_aes_param { u8 protkey[64]; /* WKa(K)|WKaVP */ }; struct cpacf_km_xts_aes_128_param { u8 protkey[48]; /* WKa(K)|WKaVP */ u8 xtsparam[16]; }; struct cpacf_km_xts_aes_256_param { u8 protkey[64]; /* WKa(K)|WKaVP */ u8 xtsparam[16]; }; static inline int cpacf_km(unsigned long fc, void *param, u8 * out, const u8 * in, unsigned long inlen) { /* *INDENT-OFF* */ register unsigned long r0 asm("0") = (unsigned long) fc; register unsigned long r1 asm("1") = (unsigned long) param; register unsigned long r2 asm("2") = (unsigned long) in; register unsigned long r3 asm("3") = (unsigned long) inlen; register unsigned long r4 asm("4") = (unsigned long) out; u8 cc; asm volatile( "0: .insn rre,%[opc] << 16,%[out],%[in]\n" " brc 1,0b\n" /* handle partial completion */ " ipm %[cc]\n" " srl %[cc],28\n" : [in] "+a" (r2), [inlen] "+d" (r3), [out] "+a" (r4), [cc] "=d" (cc) : [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb92e) : "cc", "memory" ); /* *INDENT-ON* */ return cc; } /* KMC */ /* Function codes */ # define CPACF_KMC_QUERY 0 # define CPACF_KMC_ENCRYPTED_AES_128 26 # define CPACF_KMC_ENCRYPTED_AES_192 27 # define CPACF_KMC_ENCRYPTED_AES_256 28 struct cpacf_kmc_aes_param { u8 cv[16]; u8 protkey[64]; /* WKa(K)|WKaVP */ }; static inline int cpacf_kmc(unsigned long fc, void *param, u8 * out, const u8 * in, long inlen) { /* *INDENT-OFF* */ register unsigned long r0 asm("0") = (unsigned long) fc; register unsigned long r1 asm("1") = (unsigned long) param; register unsigned long r2 asm("2") = (unsigned long) in; register unsigned long r3 asm("3") = (unsigned long) inlen; register unsigned long r4 asm("4") = (unsigned long) out; u8 cc; asm volatile( "0: .insn rre,%[opc] << 16,%[out],%[in]\n" " brc 1,0b\n" /* handle partial completion */ " ipm %[cc]\n" " srl %[cc],28\n" : [in] "+a" (r2), [inlen] "+d" (r3), [out] "+a" (r4), [cc] "=d" (cc) : [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb92f) : "cc", "memory" ); /* *INDENT-ON* */ return cc; } /* KMAC */ /* Function codes */ # define CPACF_KMAC_QUERY 0 # define CPACF_KMAC_ENCRYPTED_AES_128 26 # define CPACF_KMAC_ENCRYPTED_AES_192 27 # define CPACF_KMAC_ENCRYPTED_AES_256 28 struct cpacf_kmac_aes_param { u8 icv[16]; u8 protkey[64]; /* WKa(K)|WKaVP */ }; static inline int cpacf_kmac(unsigned long fc, void *param, const u8 * in, unsigned long inlen) { /* *INDENT-OFF* */ register unsigned long r0 asm("0") = (unsigned long)fc; register unsigned long r1 asm("1") = (unsigned long)param; register unsigned long r2 asm("2") = (unsigned long)in; register unsigned long r3 asm("3") = (unsigned long)inlen; u8 cc; asm volatile( "0: .insn rre,%[opc] << 16,0,%[in]\n" " brc 1,0b\n" /* handle partial completion */ " ipm %[cc]\n" " srl %[cc],28\n" : [in] "+a" (r2), [inlen] "+d" (r3), [cc] "=d" (cc) : [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb91e) : "cc", "memory" ); /* *INDENT-ON* */ return cc; } /* PCC */ /* Function codes */ # define CPACF_PCC_QUERY 0 # define CPACF_PCC_CMAC_ENCRYPTED_AES_128 26 # define CPACF_PCC_CMAC_ENCRYPTED_AES_192 27 # define CPACF_PCC_CMAC_ENCRYPTED_AES_256 28 # define CPACF_PCC_XTS_ENCRYPTED_AES_128 58 # define CPACF_PCC_XTS_ENCRYPTED_AES_256 60 struct cpacf_pcc_xts_aes_128_param { u8 protkey[48]; /* WKa(K)|WKaVP */ u8 i[16]; u8 j[16]; u8 t[16]; u8 xtsparams[16]; }; struct cpacf_pcc_xts_aes_256_param { u8 protkey[64]; /* WKa(K)|WKaVP */ u8 i[16]; u8 j[16]; u8 t[16]; u8 xtsparams[16]; }; struct cpacf_pcc_cmac_aes_param { u8 ml; u8 reserved[7]; u8 message[16]; u8 icv[16]; u8 protkey[64]; /* WKa(K)|WKaVP */ }; /* PCC (perform cryptographuc computation) */ static inline int cpacf_pcc(unsigned long fc, void *param) { register unsigned long r0 __asm__("0") = (unsigned long)fc; register unsigned long r1 __asm__("1") = (unsigned long)param; u8 cc; /* *INDENT-OFF* */ asm volatile( "0: .insn rre,%[opc] << 16,0,0\n" /* PCC opcode */ " brc 1,0b\n" /* handle partial completion */ " ipm %[cc]\n" " srl %[cc],28\n" : [cc] "=d" (cc) : [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb92c) : "cc", "memory" ); /* *INDENT-ON* */ return cc; } /* KMA */ /* Function codes */ # define CPACF_KMA_QUERY 0 # define CPACF_KMA_GCM_ENCRYPTED_AES_128 26 # define CPACF_KMA_GCM_ENCRYPTED_AES_192 27 # define CPACF_KMA_GCM_ENCRYPTED_AES_256 28 /* Function code flags */ # define CPACF_KMA_LPC 0x100/* Last-Plaintext/Ciphertext */ # define CPACF_KMA_LAAD 0x200/* Last-AAD */ # define CPACF_KMA_HS 0x400/* Hash-subkey Supplied */ struct cpacf_kma_gcm_aes_param { u8 reserved[12]; u32 cv; u8 t[16]; u8 h[16]; u64 taadl; u64 tpcl; u8 j0[16]; u8 protkey[64]; /* WKa(K)|WKaVP */ }; /* KMA (cipher message with authentication) */ static inline int cpacf_kma(unsigned long fc, void *param, u8 * out, const u8 * aad, unsigned long aadlen, const u8 * in, unsigned long inlen) { /* *INDENT-OFF* */ register unsigned long r0 __asm__("0") = (unsigned long)fc; register unsigned long r1 __asm__("1") = (unsigned long)param; register unsigned long r2 __asm__("2") = (unsigned long)in; register unsigned long r3 __asm__("3") = (unsigned long)inlen; register unsigned long r4 __asm__("4") = (unsigned long)aad; register unsigned long r5 __asm__("5") = (unsigned long)aadlen; register unsigned long r6 __asm__("6") = (unsigned long)out; u8 cc; __asm__ volatile( "0: .insn rrf,%[opc]<<16,%[out],%[in],%[aad],0\n" " brc 1,0b\n" /* partial completion */ " ipm %[cc]\n" " srl %[cc],28\n" : [out] "+a" (r6), [cc] "=d" (cc), [in] "+a" (r2), [inlen] "+d" (r3), [aad] "+a" (r4), [aadlen] "+d" (r5) : [fc] "d" (r0), [param] "a" (r1), [opc] "i" (0xb929) : "cc", "memory" ); /* *INDENT-ON* */ return cc; } #endif libzpc-1.0.0/src/debug.h000066400000000000000000000023331413160260300150160ustar00rootroot00000000000000 /* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef DEBUG_H # define DEBUG_H # include "globals.h" # include # include # include # include # include # include # include "misc.h" # define __FILENAME__ \ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) # define DEBUG(...) \ do { \ if (debug) { \ int __rc; \ \ UNUSED(__rc); \ \ __rc = pthread_mutex_lock(&debuglock); \ assert(__rc == 0); \ \ fprintf(stderr, "libzpc %d.%d.%d: pid %llu: tid %llu: %s: %s:%d: ", \ ZPC_VERSION_MAJOR, ZPC_VERSION_MINOR, ZPC_VERSION_PATCH, \ (unsigned long long)getpid(), \ (unsigned long long)syscall(SYS_gettid), \ __func__, __FILENAME__, __LINE__); \ fprintf(stderr, __VA_ARGS__); \ fprintf(stderr, "\n"); \ \ __rc = pthread_mutex_unlock(&debuglock); \ assert(__rc == 0); \ } \ } while (0) #endif libzpc-1.0.0/src/error.c000066400000000000000000000033731413160260300150610ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "zpc/error.h" #include /* * Map error code to error string. */ const char * zpc_error_string(int err) { /* Error string index equals error code. */ static const char *errstr[] = { "success", "argument 1 NULL", "argument 2 NULL", "argument 3 NULL", "argument 4 NULL", "argument 5 NULL", "argument 6 NULL", "argument 7 NULL", "argument 8 NULL", "argument 1 out of range", "argument 2 out of range", "argument 3 out of range", "argument 4 out of range", "argument 5 out of range", "argument 6 out of range", "argument 7 out of range", "argument 8 out of range", "malloc failed", "no key is set", "invalid key size", "IV not set", "invalid IV size", "invalid tag size", "tag mismatch", "function not supported", "output buffer too small", "APQNs not set", "invalid key type", "key type not set", "PKEY_GENSECK2 ioctl failed", "PKEY_CLR2SECK2 ioctl failed", "PKEY_BLOB2PROTK2 ioctl failed", "wrapping key verification pattern mismatch", "opening /dev/pkey failed", "ciphertext too long", "message too long", "additional authenticated data too long", "RESERVED", "parse error", "APQN not found in APQN list", "MKVP too long", "RESERVED", "initializing a lock failed", "object is in use", "PKEY_APQNS4KT ioctl failed", "key-size not set", "PKEY_GENPROTK ioctl failed", "protected-key only", "keys are equal", "not supported", "LAST" }; const char *rc; if (err < 0 || (size_t)err >= sizeof(errstr) / sizeof(errstr[0])) rc = "undefined error code"; else rc = errstr[err]; return rc; } libzpc-1.0.0/src/globals.c000066400000000000000000000247121413160260300153530ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "aes_key_local.h" #include "cpacf.h" #include "globals.h" #include "misc.h" #include "debug.h" #include #include #include #include #include #include #include #include #include #include #define ENV_DEBUG "ZPC_DEBUG" /* * IBM z/Architecture Principles of Operation (POP) counts bits * from most-significant/leftmost to least-significant/rightmost, * starting at 0. * If the bits returned by STFLE (facility list) or the bits * returned by a CPACF instruction's query function (status word) * are stored in an u64 array, the macros below can be used to * check a specific bit using its number from POP. * For example, checking facility bit 146: * u64 *flist; * [...] // store facility list at flist * if (flist[OFF64(146)] & MASK64(146)) [...]; */ /* Map a facility bit number or function code to its bit mask. */ #define MASK64(n) (1ULL << (63 - (n) % 64)) /* Map a facility bit number or function code to its offset. */ #define OFF64(n) (n / 64) /* Facility bit numbers */ #define MSA 17 /* message-security-assist */ #define MSA3 76 /* message-security-assist extension 3 */ #define MSA4 77 /* message-security-assist extension 4 */ #define MSA5 57 /* message-security-assist extension 5 */ #define MSA8 146 /* message-security-assist extension 8 (implies MSA3) */ #define MSA9 155 /* message-security-assist extension 9 (implies MSA3 * and MSA4) */ /* STFLE (store facility list extended) */ static inline unsigned long stfle(u64 flist[], u8 nmemb) { /* *INDENT-OFF* */ register unsigned long r0 __asm__("0") = (unsigned long)nmemb - 1; __asm__ volatile( ".insn s,%[opc]<<16,0(%[flist])" : "+d" (r0) : [flist] "a" (flist), [opc] "i" (0xb2b0) : "memory", "cc" ); /* *INDENT-ON* */ return r0 + 1; } /* * libzpc is initialized iff pkeyfd >= 0. * * Make sure this global (or another one from this compilation unit) * is referenced from all other compilation units that require the * constructor to run (that is probably all units except for the * error unit). * In case libzpc was compiled to a static library/archive, this makes sure * that the object file corresponding to this compilation unit is included * when the archive is linked with another binary. * This is because this file's constructor and destructor are required * for libzpc to work properly but are never referenced otherwise, * so the linker will generally not pick this object from the archive * unless the --whole-archive option was specified. */ int pkeyfd = -1; struct hwcaps hwcaps; int debug; pthread_mutex_t debuglock; struct cca_lib cca; pthread_mutex_t ccalock; struct ep11_lib ep11; pthread_mutex_t ep11lock; #if !defined(__linux__) && !defined(__s390x__) static const int init = 0; #else static const int init = 1; #endif __attribute__((constructor)) static void zpc_init(void) { unsigned long hwcap, facility_list_nmemb; u64 status_word[2], *facility_list = NULL, tmp; int rc, err = -1; int aes_ecb_km; int aes_cbc_kmc; int aes_gcm_kma; int aes_cmac_kmac = 0, aes_cmac_pcc = 0; int aes_ccm_kmac = 0, aes_ccm_kma = 0; int aes_xts_km = 0, aes_xts_pcc = 0; char *env; if (init != 1) return; /* Init debuggind. */ rc = pthread_mutex_init(&debuglock, NULL); if (rc) goto ret; env = getenv(ENV_DEBUG); if (env != NULL && env[0] != '\0') { char *endptr; long debuglong = strtol(env, &endptr, 0); if (*endptr == '\0' && debuglong > INT_MIN && debuglong < INT_MAX) debug = (int)debuglong; } /* Init CCA library structure. */ rc = pthread_mutex_init(&ccalock, NULL); if (rc) goto ret; rc = pthread_mutex_lock(&ccalock); assert(rc == 0); if (load_cca_library(&cca, true) != 0) DEBUG("loading CCA library failed"); else DEBUG("loaded CCA library: ver %u, rel %u, mod %u", cca.version.ver, cca.version.rel, cca.version.mod); rc = pthread_mutex_unlock(&ccalock); assert(rc == 0); /* Init EP11 library structure. */ rc = pthread_mutex_init(&ep11lock, NULL); if (rc) goto ret; rc = pthread_mutex_lock(&ep11lock); assert(rc == 0); if (load_ep11_library(&ep11, true) != 0) DEBUG("loading EP11 library failed"); else DEBUG("loaded EP11 library: %u.%u", ep11.version.major, ep11.version.minor); rc = pthread_mutex_unlock(&ep11lock); assert(rc == 0); pkeyfd = open("/dev/pkey", O_RDWR); if (pkeyfd < 0) { DEBUG("opening /dev/pkey failed"); goto ret; } DEBUG("opened /dev/pkey: file descriptor %d", pkeyfd); /* Check for STFLE. */ hwcap = getauxval(AT_HWCAP); if (!(hwcap & HWCAP_S390_STFLE)) goto ret; /* Query number of u64s returned by stfle. */ facility_list_nmemb = stfle(&tmp, 1); if (facility_list_nmemb > UINT8_MAX) goto ret; /* Expected facility list size is 64 * facility_list_nmemb bits. */ facility_list = calloc(sizeof(u64), facility_list_nmemb); if (facility_list == NULL) goto ret; /* Query facility list. */ stfle(facility_list, facility_list_nmemb); /* Check MSA. */ if (facility_list_nmemb >= OFF64(MSA) + 1 && (facility_list[OFF64(MSA)] & MASK64(MSA))) { DEBUG("detected message-security-assist"); memset(status_word, 0, sizeof(status_word)); cpacf_km(CPACF_KM_QUERY, &status_word, NULL, NULL, 0); DEBUG("status word km: 0x%016llx:0x%016llx", status_word[0], status_word[1]); if ((status_word[OFF64(CPACF_KM_ENCRYPTED_AES_128)] & MASK64(CPACF_KM_ENCRYPTED_AES_128)) && (status_word[OFF64(CPACF_KM_ENCRYPTED_AES_192)] & MASK64(CPACF_KM_ENCRYPTED_AES_192)) && (status_word[OFF64(CPACF_KM_ENCRYPTED_AES_256)] & MASK64(CPACF_KM_ENCRYPTED_AES_256))) { aes_ecb_km = 1; } if ((status_word[OFF64(CPACF_KM_XTS_ENCRYPTED_AES_128)] & MASK64(CPACF_KM_XTS_ENCRYPTED_AES_128)) && (status_word[OFF64(CPACF_KM_XTS_ENCRYPTED_AES_256)] & MASK64(CPACF_KM_XTS_ENCRYPTED_AES_256))) { aes_xts_km = 1; } memset(status_word, 0, sizeof(status_word)); cpacf_kmc(CPACF_KMC_QUERY, &status_word, NULL, NULL, 0); DEBUG("status word kmc: 0x%016llx:0x%016llx", status_word[0], status_word[1]); if ((status_word[OFF64(CPACF_KMC_ENCRYPTED_AES_128)] & MASK64(CPACF_KMC_ENCRYPTED_AES_128)) && (status_word[OFF64(CPACF_KMC_ENCRYPTED_AES_192)] & MASK64(CPACF_KMC_ENCRYPTED_AES_192)) && (status_word[OFF64(CPACF_KMC_ENCRYPTED_AES_256)] & MASK64(CPACF_KMC_ENCRYPTED_AES_256))) { aes_cbc_kmc = 1; } memset(status_word, 0, sizeof(status_word)); cpacf_kmac(CPACF_KMAC_QUERY, &status_word, NULL, 0); DEBUG("status word kmac: 0x%016llx:0x%016llx", status_word[0], status_word[1]); if ((status_word[OFF64(CPACF_KMAC_ENCRYPTED_AES_128)] & MASK64(CPACF_KMAC_ENCRYPTED_AES_128)) && (status_word[OFF64(CPACF_KMAC_ENCRYPTED_AES_192)] & MASK64(CPACF_KMAC_ENCRYPTED_AES_192)) && (status_word[OFF64(CPACF_KMAC_ENCRYPTED_AES_256)] & MASK64(CPACF_KMAC_ENCRYPTED_AES_256))) { aes_cmac_kmac = 1; aes_ccm_kmac = 1; } } /* Check MSA3. */ if (facility_list_nmemb >= OFF64(MSA3) + 1 && (facility_list[OFF64(MSA3)] & MASK64(MSA3))) { DEBUG("detected message-security-assist extension 3"); memset(status_word, 0, sizeof(status_word)); cpacf_pcc(CPACF_PCC_QUERY, &status_word); DEBUG("status word pcc: 0x%016llx:0x%016llx", status_word[0], status_word[1]); if ((status_word[OFF64(CPACF_PCC_CMAC_ENCRYPTED_AES_128)] & MASK64(CPACF_PCC_CMAC_ENCRYPTED_AES_128)) && (status_word[OFF64(CPACF_PCC_CMAC_ENCRYPTED_AES_192)] & MASK64(CPACF_PCC_CMAC_ENCRYPTED_AES_192)) && (status_word[OFF64(CPACF_PCC_CMAC_ENCRYPTED_AES_256)] & MASK64(CPACF_PCC_CMAC_ENCRYPTED_AES_256))) { aes_cmac_pcc = 1; } if ((status_word[OFF64(CPACF_PCC_XTS_ENCRYPTED_AES_128)] & MASK64(CPACF_PCC_XTS_ENCRYPTED_AES_128)) && (status_word[OFF64(CPACF_PCC_XTS_ENCRYPTED_AES_256)] & MASK64(CPACF_PCC_XTS_ENCRYPTED_AES_256))) { aes_xts_pcc = 1; } } /* Check MSA8. */ if (facility_list_nmemb >= OFF64(MSA8) + 1 && (facility_list[OFF64(MSA8)] & MASK64(MSA8))) { DEBUG("detected message-security-assist extension 8"); memset(status_word, 0, sizeof(status_word)); cpacf_kma(CPACF_KMA_QUERY, &status_word, NULL, NULL, 0, NULL, 0); DEBUG("status word kma: 0x%016llx:0x%016llx", status_word[0], status_word[1]); if ((status_word[OFF64(CPACF_KMA_GCM_ENCRYPTED_AES_128)] & MASK64(CPACF_KMA_GCM_ENCRYPTED_AES_128)) && (status_word[OFF64(CPACF_KMA_GCM_ENCRYPTED_AES_192)] & MASK64(CPACF_KMA_GCM_ENCRYPTED_AES_192)) && (status_word[OFF64(CPACF_KMA_GCM_ENCRYPTED_AES_256)] & MASK64(CPACF_KMA_GCM_ENCRYPTED_AES_256))) { aes_ccm_kma = 1; aes_gcm_kma = 1; } } if (aes_ecb_km == 1) { hwcaps.aes_ecb = 1; DEBUG("detected aes-ecb instruction set extensions"); } if (aes_cbc_kmc == 1) { hwcaps.aes_cbc = 1; DEBUG("detected aes-cbc instruction set extensions"); } if (aes_xts_km == 1 && aes_xts_pcc) { hwcaps.aes_xts = 1; DEBUG("detected aes-xts instruction set extensions"); } if (aes_cmac_kmac == 1 && aes_cmac_pcc == 1) { hwcaps.aes_cmac = 1; DEBUG("detected aes-cmac instruction set extensions"); } if (aes_ccm_kma == 1 && aes_ccm_kmac == 1) { hwcaps.aes_ccm = 1; DEBUG("detected aes-ccm instruction set extensions"); } if (aes_gcm_kma == 1) { hwcaps.aes_gcm = 1; DEBUG("detected aes-gcm instruction set extensions"); } err = 0; ret: if (err) { if (pkeyfd >= 0) { close(pkeyfd); pkeyfd = -1; } } free(facility_list); DEBUG("return"); return; } __attribute__((destructor)) static void zpc_fini(void) { int rc; UNUSED(rc); if (init != 1) return; if (pkeyfd >= 0) { close(pkeyfd); pkeyfd = -1; } /* Unload EP11 library. */ rc = pthread_mutex_lock(&ep11lock); assert(rc == 0); if (ep11.lib_ep11 != NULL) dlclose(ep11.lib_ep11); rc = pthread_mutex_unlock(&ep11lock); assert(rc == 0); rc = pthread_mutex_destroy(&ep11lock); assert(rc == 0); /* Unload CCA library. */ rc = pthread_mutex_lock(&ccalock); assert(rc == 0); if (cca.lib_csulcca != NULL) dlclose(cca.lib_csulcca); rc = pthread_mutex_unlock(&ccalock); assert(rc == 0); rc = pthread_mutex_destroy(&ccalock); assert(rc == 0); DEBUG("return"); rc = pthread_mutex_destroy(&debuglock); assert(rc == 0); } libzpc-1.0.0/src/globals.h000066400000000000000000000013641413160260300153560ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef GLOBALS_H # define GLOBALS_H # include # include # include "zkey/cca.h" # include "zkey/ep11.h" struct hwcaps { int aes_gcm; int aes_ccm; int aes_ecb; int aes_cbc; int aes_xts; int aes_cmac; }; /* * Globals are initialized at the library's constructor * and are read-only or lock-protected afterwards. */ extern int pkeyfd; extern struct hwcaps hwcaps; extern int debug; extern pthread_mutex_t debuglock; extern struct cca_lib cca; extern pthread_mutex_t ccalock; extern struct ep11_lib ep11; extern pthread_mutex_t ep11lock; #endif libzpc-1.0.0/src/misc.c000066400000000000000000000035631413160260300146640ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "misc.h" #include #include #include static int ishexdigit(const char); static unsigned char hexdigit2byte(char); static char byte2hexdigit(unsigned char); int hexstr2buf(u8 * buf, size_t *buflen, const char *hex) { size_t i; assert(buf != NULL); assert(buflen != NULL); assert(*buflen != 0); assert(hex != NULL); /* Skip possible leading '0x'. */ if (strlen(hex) >= 2 && hex[0] == '0' && hex[1] == 'x') hex += 2; if (strlen(hex) == 0 || strlen(hex) % 2 != 0 || strlen(hex) / 2 > *buflen) return -1; memset(buf, 0, *buflen); for (i = 0; i + 1 < strlen(hex); i += 2) { if (!ishexdigit(hex[i]) || !ishexdigit(hex[i + 1])) return -1; /* Parse error. */ buf[i / 2] = hexdigit2byte(hex[i]) << 4; buf[i / 2] += hexdigit2byte(hex[i + 1]); } *buflen = strlen(hex) / 2; return 0; } void buf2hexstr(char *hex, size_t hexlen, const unsigned char *buf, size_t buflen) { size_t i; assert(hex != NULL); assert(buf != NULL); assert(buflen > 0); assert(hexlen >= 2 * buflen); memset(hex, 0, hexlen); for (i = 0; i < buflen; i++) { hex[2 * i] = byte2hexdigit(buf[i] >> 4); hex[2 * i + 1] = byte2hexdigit(buf[i] & 0xf); } hex[2 * i] = '\0'; } static int ishexdigit(const char d) { return ((d >= '0' && d <= '9') || (d >= 'A' && d <= 'F') || (d >= 'a' && d <= 'f')); } static unsigned char hexdigit2byte(char d) { const char noff = '0' - 0; const char uoff = 'A' - 10; const char loff = 'a' - 10; return (d >= 'a' ? d - loff : (d >= 'A' ? d - uoff : d - noff)); } static char byte2hexdigit(unsigned char b) { const char noff = '0' - 0; const char loff = 'a' - 10; assert((b & 0xf0) == 0); return (b >= 10 ? b + loff : b + noff); } libzpc-1.0.0/src/misc.h000066400000000000000000000012361413160260300146640ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef MISC_H # define MISC_H # include # define UNUSED(x) (void)(x) # define NMEMB(x) (sizeof(x) / sizeof(x[0])) # define __packed __attribute__((packed)) typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; void memzero_secure(void *, size_t); int memcmp_consttime(const void *, const void *, size_t); int hexstr2buf(u8 *, size_t *, const char *); void buf2hexstr(char *, size_t, const unsigned char *, size_t); #endif libzpc-1.0.0/src/misc_asm.S000066400000000000000000000025421413160260300155000ustar00rootroot00000000000000# # Copyright IBM Corp. 2021 # # libzpc is free software; you can redistribute it and/or modify # it under the terms of the MIT license. See LICENSE for details. # .text # void memzero_secure(void *buf, size_t buflen) .globl memzero_secure .type memzero_secure,@function .align 16 memzero_secure: .cfi_startproc ltgr %r3,%r3 ber %r14 aghi %r3,-1 srlg %r1,%r3,8 ltgr %r1,%r1 je .Lmemzero_secure_skip .Lmemzero_secure_oop: xc 0(256,%r2),0(%r2) la %r2,256(%r2) brctg %r1,.Lmemzero_secure_oop .Lmemzero_secure_skip: larl %r1,.Lmemzero_secure_xc ex %r3,0(%r1) br %r14 .Lmemzero_secure_xc: xc 0(1,%r2),0(%r2) .cfi_endproc .size memzero_secure, .-memzero_secure # int memcmp_consttime(const void *buf1, const void *buf2, size_t buflen) .globl memcmp_consttime .type memcmp_consttime,@function .align 16 memcmp_consttime: .cfi_startproc lghi %r5,0 clgr %r4,%r5 je .Lmemcmp_consttime_skip .Lmemcmp_consttime_loop: llgc %r0,0(%r2) la %r2,1(%r2) llgc %r1,0(%r3) la %r3,1(%r3) xr %r1,%r0 or %r5,%r1 brctg %r4,.Lmemcmp_consttime_loop lnr %r5,%r5 srl %r5,31 .Lmemcmp_consttime_skip: lgr %r2,%r5 br %r14 .cfi_endproc .size memcmp_consttime, .-memcmp_consttime .size memcmp_consttime,.-memcmp_consttime libzpc-1.0.0/src/zkey/000077500000000000000000000000001413160260300145405ustar00rootroot00000000000000libzpc-1.0.0/src/zkey/README000066400000000000000000000002521413160260300154170ustar00rootroot00000000000000zpc_aes_key_reencipher used modified zkey code from s390-tools-2.18 as a library to reencipher secure keys: https://github.com/ibm-s390-linux/s390-tools/tree/master/zkey libzpc-1.0.0/src/zkey/cca.c000066400000000000000000000425611413160260300154420ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * Copyright IBM Corp. 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include #include #include #include #include "lib/util_base.h" #include "lib/util_libc.h" #include "lib/util_panic.h" #include "cca.h" #include "pkey.h" #include "utils.h" #include "debug.h" #define pr_verbose(verbose, fmt...) do { \ if (verbose) \ DEBUG(fmt); \ } while (0) /* * Definitions for the CCA library */ #define CCA_LIBRARY_NAME "libcsulcca.so" #define CCA_WEB_PAGE "http://www.ibm.com/security/cryptocards" #define CCA_DOMAIN_ENVAR "CSU_DEFAULT_DOMAIN" #define CCA_ADAPTER_ENVAR "CSU_DEFAULT_ADAPTER" /** * Prints CCA return and reason code information for certain known CCA * error situations. * * @param return_code the CCA return code * @param reason_code the CCA reason code */ static void print_CCA_error(int return_code, int reason_code) { switch (return_code) { case 8: switch (reason_code) { case 48: DEBUG("The secure key has a CCA master key " "verification pattern that is not valid"); break; case 90: DEBUG("The operation has been rejected due to access " "control checking"); break; case 2143: DEBUG("The operation has been rejected due to key " "export restrictions of the secure key"); break; } break; case 12: switch (reason_code) { case 764: DEBUG("The CCA master key is not loaded and " "therefore a secure key cannot be enciphered"); break; } break; } } /** * Returns the version, release and modification number of the used CCA library. * * @param[in] cca the CCA library structure * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of an error */ static int get_cca_version(struct cca_lib *cca, bool verbose) { unsigned char exit_data[4] = { 0, }; unsigned char version_data[20]; long return_code, reason_code; long version_data_length; long exit_data_len = 0; char date[20]; util_assert(cca != NULL, "Internal error: cca is NULL"); memset(version_data, 0, sizeof(version_data)); version_data_length = sizeof(version_data); cca->dll_CSUACFV(&return_code, &reason_code, &exit_data_len, exit_data, &version_data_length, version_data); pr_verbose(verbose, "CSUACFV (Cryptographic Facility Version) " "returned: return_code: %ld, reason_code: %ld", return_code, reason_code); if (return_code != 0) { print_CCA_error(return_code, reason_code); return -EIO; } version_data[sizeof(version_data) - 1] = '\0'; pr_verbose(verbose, "CCA Version string: %s", version_data); if (sscanf((char *)version_data, "%u.%u.%uz%s", &cca->version.ver, &cca->version.rel, &cca->version.mod, date) != 4) { DEBUG("CCA library version is invalid: %s", version_data); return -EINVAL; } return 0; } /** * Loads the CCA library and provides the entry point of the CSNBKTC function. * * @param[out] cca on return this contains the address of the CCA * library and certain CCA symbols. dlclose() should * be used to free the library when no longer needed. * @param verbose if true, verbose messages are printed * * @returns 0 on success, -ELIBACC in case of library load errors */ int load_cca_library(struct cca_lib *cca, bool verbose) { util_assert(cca != NULL, "Internal error: caa is NULL"); /* Load the CCA library */ cca->lib_csulcca = dlopen(CCA_LIBRARY_NAME, RTLD_GLOBAL | RTLD_NOW); if (cca->lib_csulcca == NULL) { pr_verbose(verbose, "%s", dlerror()); DEBUG("The command requires the IBM CCA Host Libraries and " "Tools.\nFor the supported environments and downloads, " "see:\n%s", CCA_WEB_PAGE); return -ELIBACC; } /* Get the Cryptographic Facility Version function */ cca->dll_CSUACFV = (t_CSUACFV)dlsym(cca->lib_csulcca, "CSUACFV"); /* Get the Key Token Change function */ cca->dll_CSNBKTC = (t_CSNBKTC)dlsym(cca->lib_csulcca, "CSNBKTC"); /* Get the Key Token Change 2 function */ cca->dll_CSNBKTC2 = (t_CSNBKTC2)dlsym(cca->lib_csulcca, "CSNBKTC2"); /* Get the Cryptographic Facility Query function */ cca->dll_CSUACFQ = (t_CSUACFQ)dlsym(cca->lib_csulcca, "CSUACFQ"); /* Get the Cryptographic Resource Allocate function */ cca->dll_CSUACRA = (t_CSUACRA)dlsym(cca->lib_csulcca, "CSUACRA"); /* Cryptographic Resource Deallocate function */ cca->dll_CSUACRD = (t_CSUACRD)dlsym(cca->lib_csulcca, "CSUACRD"); /* Get the Key Token Build 2 function */ cca->dll_CSNBKTB2 = (t_CSNBKTB2)dlsym(cca->lib_csulcca, "CSNBKTB2"); /* Get the Key Translate 2 function */ cca->dll_CSNBKTR2 = (t_CSNBKTR2)dlsym(cca->lib_csulcca, "CSNBKTR2"); /* Get the Restrict Key Attribute function */ cca->dll_CSNBRKA = (t_CSNBRKA)dlsym(cca->lib_csulcca, "CSNBRKA"); if (cca->dll_CSUACFV == NULL || cca->dll_CSNBKTC == NULL || cca->dll_CSNBKTC2 == NULL || cca->dll_CSUACFQ == NULL || cca->dll_CSUACRA == NULL || cca->dll_CSUACRD == NULL || cca->dll_CSNBKTB2 == NULL || cca->dll_CSNBKTR2 == NULL || cca->dll_CSNBRKA == NULL) { pr_verbose(verbose, "%s", dlerror()); DEBUG("The command requires the IBM CCA Host Libraries and " "Tools.\nFor the supported environments and downloads, " "see:\n%s", CCA_WEB_PAGE); dlclose(cca->lib_csulcca); cca->lib_csulcca = NULL; return -ELIBACC; } pr_verbose(verbose, "CCA library '%s' has been loaded successfully", CCA_LIBRARY_NAME); return get_cca_version(cca, verbose); } /** * Re-enciphers a secure key. * * @param[in] cca the CCA libraray structure * @param[in] secure_key a buffer containing the secure key * @param[in] secure_key_size the size of the secure key * @param[in] method the re-enciphering method. METHOD_OLD_TO_CURRENT * or METHOD_CURRENT_TO_NEW. * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, -EIO in case of an error */ int key_token_change(struct cca_lib *cca, u8 *secure_key, unsigned int secure_key_size, char *method, bool verbose) { struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)secure_key; long exit_data_len = 0, rule_array_count; unsigned char rule_array[2 * 8] = { 0, }; unsigned char exit_data[4] = { 0, }; long return_code, reason_code; long key_token_length; util_assert(cca != NULL, "Internal error: cca is NULL"); util_assert(secure_key != NULL, "Internal error: secure_key is NULL"); util_assert(secure_key_size > 0, "Internal error: secure_key_size is 0"); util_assert(method != NULL, "Internal error: method is NULL"); memcpy(rule_array, method, 8); memcpy(rule_array + 8, "AES ", 8); rule_array_count = 2; if (is_cca_aes_data_key(secure_key, secure_key_size)) { cca->dll_CSNBKTC(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, secure_key); pr_verbose(verbose, "CSNBKTC (Key Token Change) with '%s' " "returned: return_code: %ld, reason_code: %ld", method, return_code, reason_code); } else if (is_cca_aes_cipher_key(secure_key, secure_key_size)) { key_token_length = cipherkey->length; cca->dll_CSNBKTC2(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &key_token_length, (unsigned char *)cipherkey); pr_verbose(verbose, "CSNBKTC2 (Key Token Change2) with '%s' " "returned: return_code: %ld, reason_code: %ld", method, return_code, reason_code); pr_verbose(verbose, "key_token_length: %lu", key_token_length); } else { DEBUG("Invalid key type specified"); return -EINVAL; } if (return_code != 0) { print_CCA_error(return_code, reason_code); return -EIO; } if (is_xts_key(secure_key, secure_key_size)) { if (is_cca_aes_data_key(secure_key, secure_key_size)) { cca->dll_CSNBKTC(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, secure_key + AESDATA_KEY_SIZE); pr_verbose(verbose, "CSNBKTC (Key Token Change) with " "'%s' returned: return_code: %ld, " "reason_code: %ld", method, return_code, reason_code); } else if (is_cca_aes_cipher_key(secure_key, secure_key_size)) { cipherkey = (struct aescipherkeytoken *)(secure_key + AESCIPHER_KEY_SIZE); key_token_length = cipherkey->length; cca->dll_CSNBKTC2(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &key_token_length, (unsigned char *)cipherkey); pr_verbose(verbose, "CSNBKTC2 (Key Token Change2) with " "'%s' returned: return_code: %ld, " "reason_code: %ld", method, return_code, reason_code); pr_verbose(verbose, "key_token_length: %lu", key_token_length); } else { DEBUG("Invalid key type specified"); return -EINVAL; } if (return_code != 0) { print_CCA_error(return_code, reason_code); return -EIO; } } return 0; } /** * Queries the number of adapters known by the CCA host library * * @param[in] cca the CCA library structure * @param[out] adapters the number of adapters * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of an error. */ static int get_number_of_cca_adapters(struct cca_lib *cca, unsigned int *adapters, bool verbose) { long exit_data_len = 0, rule_array_count, verb_data_length = 0; unsigned char rule_array[16 * 8] = { 0, }; unsigned char exit_data[4] = { 0, }; long return_code, reason_code; util_assert(cca != NULL, "Internal error: cca is NULL"); util_assert(adapters != NULL, "Internal error: adapters is NULL"); memset(rule_array, 0, sizeof(rule_array)); memcpy(rule_array, "STATCRD2", 8); rule_array_count = 1; cca->dll_CSUACFQ(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &verb_data_length, NULL); pr_verbose(verbose, "CSUACFQ (Cryptographic Facility Query) returned: " "return_code: %ld, reason_code: %ld", return_code, reason_code); if (return_code != 0) { print_CCA_error(return_code, reason_code); return -EIO; } rule_array[8] = '\0'; if (sscanf((char *)rule_array, "%u", adapters) != 1) { pr_verbose(verbose, "Unparsable output: %s", rule_array); return -EIO; } pr_verbose(verbose, "Number of CCA adapters: %u", *adapters); return 0; } /** * Allocate a specific CCA adapter. * * @param[in] cca the CCA library structure * @param[in] adapter the adapter number, starting at 1. If 0 is * specified, then the AUTOSELECT option is * enabled. * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of an error. -ENODEV is * returned if the adapter is not available. */ static int allocate_cca_adapter(struct cca_lib *cca, unsigned int adapter, bool verbose) { long exit_data_len = 0, rule_array_count; unsigned char rule_array[8] = { 0, }; unsigned char exit_data[4] = { 0, }; long return_code, reason_code; char res_name[9]; long res_name_len; util_assert(cca != NULL, "Internal error: cca is NULL"); if (adapter > 0) memcpy(rule_array, "DEVICE ", 8); else memcpy(rule_array, "DEV-ANY ", 8); rule_array_count = 1; sprintf(res_name, "CRP%02d", adapter); res_name_len = strlen(res_name); cca->dll_CSUACRA(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &res_name_len, (unsigned char *)res_name); pr_verbose(verbose, "CSUACRA (Cryptographic Resource Allocate) " "returned: return_code: %ld, reason_code: %ld", return_code, reason_code); if (return_code != 0) { print_CCA_error(return_code, reason_code); return -ENODEV; } pr_verbose(verbose, "Adapter %u (%s) allocated", adapter, res_name); return 0; } /** * Deallocate a specific CCA adapter. * * @param[in] cca the CCA library structure * @param[in] adapter the adapter number, starting at 1. If 0 is * specified, then the AUTOSELECT option is * disabled. * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of an error. -ENODEV is * returned if the adapter is not available. */ static int deallocate_cca_adapter(struct cca_lib *cca, unsigned int adapter, bool verbose) { long exit_data_len = 0, rule_array_count; unsigned char rule_array[8] = { 0, }; unsigned char exit_data[4] = { 0, }; long return_code, reason_code; char res_name[9]; long res_name_len; util_assert(cca != NULL, "Internal error: cca is NULL"); if (adapter > 0) memcpy(rule_array, "DEVICE ", 8); else memcpy(rule_array, "DEV-ANY ", 8); rule_array_count = 1; sprintf(res_name, "CRP%02d", adapter); res_name_len = strlen(res_name); cca->dll_CSUACRD(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &res_name_len, (unsigned char *)res_name); pr_verbose(verbose, "CSUACRD (Cryptographic Resource Deallocate) " "returned: return_code: %ld, reason_code: %ld", return_code, reason_code); if (return_code != 0) { print_CCA_error(return_code, reason_code); return -ENODEV; } pr_verbose(verbose, "Adapter %u (%s) deallocated", adapter, res_name); return 0; } /** * Queries the serial number of the current CCA adapter * * @param[in] cca the CCA library structure * @param[out] serialnr the buffer where the serial number is returned * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of an error. */ static int get_cca_adapter_serialnr(struct cca_lib *cca, char serialnr[9], bool verbose) { long exit_data_len = 0, rule_array_count, verb_data_length = 0; unsigned char rule_array[16 * 8] = { 0, }; unsigned char exit_data[4] = { 0, }; long return_code, reason_code; util_assert(cca != NULL, "Internal error: cca is NULL"); memset(rule_array, 0, sizeof(rule_array)); memcpy(rule_array, "STATCRD2", 8); rule_array_count = 1; cca->dll_CSUACFQ(&return_code, &reason_code, &exit_data_len, exit_data, &rule_array_count, rule_array, &verb_data_length, NULL); pr_verbose(verbose, "CSUACFQ (Cryptographic Facility Query) returned: " "return_code: %ld, reason_code: %ld", return_code, reason_code); if (return_code != 0) { print_CCA_error(return_code, reason_code); return -EIO; } memcpy(serialnr, rule_array+14*8, 8); serialnr[8] = '\0'; pr_verbose(verbose, "Serial number of CCA adapter: %s", serialnr); return 0; } /** * Selects the specified APQN to be used for the CCA host library. * * @param[in] cca the CCA library structure * @param[in] card the card number * @param[in] domain the domain number * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of an error. -ENOTSUP is * returned when the serialnr sysfs attribute is not available, * because the zcrypt kernel module is on an older level. -ENODEV is * returned if the APQN is not available. */ int select_cca_adapter(struct cca_lib *cca, unsigned int card, unsigned int domain, bool verbose) { unsigned int adapters, adapter; char adapter_serialnr[9]; char apqn_serialnr[SERIALNR_LENGTH]; char temp[10]; int rc, found = 0; util_assert(cca != NULL, "Internal error: cca is NULL"); pr_verbose(verbose, "Select %02x.%04x for the CCA host library", card, domain); rc = sysfs_get_serialnr(card, apqn_serialnr, verbose); if (rc != 0) { pr_verbose(verbose, "Failed to get the serial number: %s", strerror(-rc)); return rc; } sprintf(temp, "%u", domain); if (setenv(CCA_DOMAIN_ENVAR, temp, 1) != 0) { rc = -errno; pr_verbose(verbose, "Failed to set the %s environment variable:" " %s", CCA_DOMAIN_ENVAR, strerror(-rc)); return rc; } unsetenv(CCA_ADAPTER_ENVAR); /* * Unload and reload the CCA host library so that it recognizes the * changed CSU_DEFAULT_DOMAIN environment variable value. */ if (cca->lib_csulcca != NULL) dlclose(cca->lib_csulcca); memset(cca, 0, sizeof(struct cca_lib)); rc = load_cca_library(cca, verbose); if (rc != 0) return rc; rc = get_number_of_cca_adapters(cca, &adapters, verbose); if (rc != 0) return rc; /* Deallocate any adapter first, in case one is already allocated */ for (adapter = 1; adapter <= adapters; adapter++) deallocate_cca_adapter(cca, adapter, false); /* Disable the AUTOSELECT option */ rc = deallocate_cca_adapter(cca, 0, verbose); if (rc != 0) return rc; for (adapter = 1; adapter <= adapters; adapter++) { rc = allocate_cca_adapter(cca, adapter, verbose); if (rc != 0) return rc; rc = get_cca_adapter_serialnr(cca, adapter_serialnr, verbose); if (rc == 0) { if (memcmp(apqn_serialnr, adapter_serialnr, 8) == 0) { found = 1; break; } } rc = deallocate_cca_adapter(cca, adapter, verbose); if (rc != 0) return rc; } if (!found) return -ENODEV; pr_verbose(verbose, "Selected adapter %u (CRP%02d)", adapter, adapter); return 0; } libzpc-1.0.0/src/zkey/cca.h000066400000000000000000000114071413160260300154420ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * This header file defines the interface to the CCA host library. * * Copyright IBM Corp. 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef CCA_H #define CCA_H #include #include "lib/zt_common.h" #define METHOD_OLD_TO_CURRENT "RTCMK " #define METHOD_CURRENT_TO_NEW "RTNMK " typedef void (*t_CSNBKTC)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, unsigned char *key_identifier); typedef void (*t_CSNBKTC2)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, long *key_identifier_length, unsigned char *key_identifier); typedef void (*t_CSUACFV)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *version_data_length, unsigned char *version_data); typedef void (*t_CSUACFQ)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, long *verb_data_length, unsigned char *verb_data); typedef void (*t_CSUACRA)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, long *ressource_name_length, unsigned char *ressource_name); typedef void (*t_CSUACRD)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, long *ressource_name_length, unsigned char *ressource_name); typedef void (*t_CSNBKTB2)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, long *clear_key_bit_length, unsigned char *clear_key_value, long *key_name_length, unsigned char *key_name, long *user_associated_data_length, unsigned char *user_associated_data, long *token_data_length, unsigned char *token_data, long *verb_data_length, unsigned char *verb_data, long *target_key_token_length, unsigned char *target_key_token); typedef void (*t_CSNBKTR2)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, long *input_key_token_length, unsigned char *input_key_token, long *input_KEK_key_identifier_length, unsigned char *input_KEK_key_identifier, long *output_KEK_key_identifier_length, unsigned char *output_KEK_key_identifier, long *output_key_token_length, unsigned char *output_key_token); typedef void (*t_CSNBRKA)(long *return_code, long *reason_code, long *exit_data_length, unsigned char *exit_data, long *rule_array_count, unsigned char *rule_array, long *key_identifier_length, unsigned char *key_identifier, long *ey_encrypting_key_identifier_length, unsigned char *ey_encrypting_key_identifier, long *opt_parameter1_length, unsigned char *opt_parameter1, long *opt_parameter2_length, unsigned char *opt_parameter2); struct cca_version { unsigned int ver; unsigned int rel; unsigned int mod; }; struct cca_lib { void *lib_csulcca; t_CSNBKTC dll_CSNBKTC; t_CSNBKTC2 dll_CSNBKTC2; t_CSUACFV dll_CSUACFV; t_CSUACFQ dll_CSUACFQ; t_CSUACRA dll_CSUACRA; t_CSUACRD dll_CSUACRD; t_CSNBKTB2 dll_CSNBKTB2; t_CSNBKTR2 dll_CSNBKTR2; t_CSNBRKA dll_CSNBRKA; struct cca_version version; }; int load_cca_library(struct cca_lib *cca, bool verbose); int key_token_change(struct cca_lib *cca, u8 *secure_key, unsigned int secure_key_size, char *method, bool verbose); int select_cca_adapter(struct cca_lib *cca, unsigned int card, unsigned int domain, bool verbose); #define FLAG_SEL_CCA_MATCH_CUR_MKVP 0x01 #define FLAG_SEL_CCA_MATCH_OLD_MKVP 0x02 #define FLAG_SEL_CCA_NEW_MUST_BE_SET 0x80 int select_cca_adapter_by_mkvp(struct cca_lib *cca, u8 *mkvp, const char *apqns, unsigned int flags, bool verbose); void print_msg_for_cca_envvars(const char *key_name); int convert_aes_data_to_cipher_key(struct cca_lib *cca, u8 *input_key, unsigned int input_key_size, u8 *output_key, unsigned int *output_key_size, bool verbose); int restrict_key_export(struct cca_lib *cca, u8 *secure_key, unsigned int secure_key_size, bool verbose); #endif libzpc-1.0.0/src/zkey/ep11.c000066400000000000000000000301331413160260300154520ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * Copyright IBM Corp. 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include #include #include #include #include "lib/util_base.h" #include "lib/util_libc.h" #include "lib/util_panic.h" #include "ep11.h" #include "pkey.h" #include "utils.h" #include "debug.h" #define pr_verbose(verbose, fmt...) do { \ if (verbose) \ DEBUG(fmt); \ } while (0) /* * Definitions for the EP11 library */ #define EP11_LIBRARY_NAME "libep11.so" #define EP11_LIBRARY_VERSION 3 #define EP11_WEB_PAGE "http://www.ibm.com/security/cryptocards" /** * Returns the major and minor version of the of the used EP11 host library. * * @param[in] ep11 the EP11 library structure * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of an error */ static int get_ep11_version(struct ep11_lib *ep11, bool verbose) { unsigned int host_version; CK_ULONG version_len = sizeof(host_version); CK_RV rc; rc = ep11->dll_m_get_xcp_info(&host_version, &version_len, CK_IBM_XCPHQ_VERSION, 0, 0); if (rc != CKR_OK) { pr_verbose(verbose, "Failed to obtain the EP11 host library " "version: m_get_xcp_info: 0x%lx", rc); return -EIO; } pr_verbose(verbose, "host_version: 0x%08x", host_version); ep11->version.major = (host_version & 0x00FF0000) >> 16; ep11->version.minor = host_version & 0x000000FF; /* * EP11 host library < v2.0 returns an invalid version (i.e. 0x100). * This can safely be treated as version 1.0 */ if (ep11->version.major == 0) { ep11->version.major = 1; ep11->version.minor = 0; } pr_verbose(verbose, "EP11 library version: %u.%u", ep11->version.major, ep11->version.minor); return 0; } /** * Loads the EP11 library and provides the entry points of several functions. * * @param[out] ep11 on return this contains the address of the EP11 * library and certain EP11 symbols. dlclose() should * be used to free the library when no longer needed. * @param verbose if true, verbose messages are printed * * @returns 0 on success, -ELIBACC in case of library load errors */ int load_ep11_library(struct ep11_lib *ep11, bool verbose) { char lib_name[256]; int libver; int rc; util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); /* Load the EP11 library with highest available version'd SO name */ for (libver = EP11_LIBRARY_VERSION; libver >= 0; libver--) { if (libver > 0) sprintf(lib_name, "%s.%d", EP11_LIBRARY_NAME, libver); else sprintf(lib_name, "%s", EP11_LIBRARY_NAME); ep11->lib_ep11 = dlopen(lib_name, RTLD_GLOBAL | RTLD_NOW); if (ep11->lib_ep11 != NULL) break; } if (ep11->lib_ep11 == NULL) { pr_verbose(verbose, "%s", dlerror()); DEBUG("The command requires the IBM Z Enterprise PKCS #11 " "(EP11) Support Program (EP11 host library).\n" "For the supported environments and downloads, see:\n%s", EP11_WEB_PAGE); return -ELIBACC; } /* Get several EP11 host library functions */ ep11->dll_m_init = (m_init_t)dlsym(ep11->lib_ep11, "m_init"); ep11->dll_m_add_module = (m_add_module_t)dlsym(ep11->lib_ep11, "m_add_module"); ep11->dll_m_rm_module = (m_rm_module_t)dlsym(ep11->lib_ep11, "m_rm_module"); ep11->dll_m_get_xcp_info = (m_get_xcp_info_t)dlsym(ep11->lib_ep11, "m_get_xcp_info"); ep11->dll_m_admin = (m_admin_t)dlsym(ep11->lib_ep11, "m_admin"); ep11->dll_xcpa_cmdblock = (xcpa_cmdblock_t)dlsym(ep11->lib_ep11, "xcpa_cmdblock"); if (ep11->dll_xcpa_cmdblock == NULL) ep11->dll_xcpa_cmdblock = (xcpa_cmdblock_t)dlsym(ep11->lib_ep11, "ep11a_cmdblock"); ep11->dll_xcpa_internal_rv = (xcpa_internal_rv_t)dlsym(ep11->lib_ep11, "xcpa_internal_rv"); if (ep11->dll_xcpa_internal_rv == NULL) ep11->dll_xcpa_internal_rv = (xcpa_internal_rv_t)dlsym(ep11->lib_ep11, "ep11a_internal_rv"); /* dll_m_add_module and dll_m_rm_module may be NULL for V1 EP11 lib */ if (ep11->dll_m_init == NULL || ep11->dll_m_get_xcp_info == NULL || ep11->dll_m_admin == NULL || ep11->dll_xcpa_cmdblock == NULL || ep11->dll_xcpa_internal_rv == NULL) { pr_verbose(verbose, "%s", dlerror()); DEBUG("The command requires the IBM Z Enterprise PKCS #11 " "(EP11) Support Program (EP11 host library).\n" "For the supported environments and downloads, see:\n%s", EP11_WEB_PAGE); dlclose(ep11->lib_ep11); ep11->lib_ep11 = NULL; return -ELIBACC; } /* Initialize the EP11 library */ rc = ep11->dll_m_init(); if (rc != 0) { pr_verbose(verbose, "Failed to initialize the EP11 host " "library: m_init: 0x%x", rc); dlclose(ep11->lib_ep11); ep11->lib_ep11 = NULL; return -ELIBACC; } pr_verbose(verbose, "EP11 library '%s' has been loaded successfully", lib_name); return get_ep11_version(ep11, verbose); } /** * Get an EP11 target handle for a specific APQN (card and domain) * * @param[in] ep11 the EP11 library structure * @param[in] card the card number * @param[in] domain the domain number * @param[out] target on return: the target handle for the APQN * @param verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of errors */ int get_ep11_target_for_apqn(struct ep11_lib *ep11, unsigned int card, unsigned int domain, target_t *target, bool verbose) { ep11_target_t *target_list; struct XCP_Module module; CK_RV rc; util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); util_assert(target != NULL, "Internal error: target is NULL"); *target = XCP_TGT_INIT; if (ep11->dll_m_add_module != NULL) { memset(&module, 0, sizeof(module)); module.version = ep11->version.major >= 3 ? XCP_MOD_VERSION_2 : XCP_MOD_VERSION_1; module.flags = XCP_MFL_MODULE; module.module_nr = card; XCPTGTMASK_SET_DOM(module.domainmask, domain); rc = ep11->dll_m_add_module(&module, target); if (rc != 0) { pr_verbose(verbose, "Failed to add APQN %02x.%04x: " "m_add_module rc=0x%lx", card, domain, rc); return -EIO; } } else { /* Fall back to old target handling */ target_list = (ep11_target_t *)calloc(1, sizeof(ep11_target_t)); if (target_list == NULL) return -ENOMEM; target_list->length = 1; target_list->apqns[0] = card; target_list->apqns[1] = domain; *target = (target_t)target_list; } return 0; } /** * Free an EP11 target handle * * @param[in] ep11 the EP11 library structure * @param[in] target the target handle to free * * @returns 0 on success, a negative errno in case of errors */ void free_ep11_target_for_apqn(struct ep11_lib *ep11, target_t target) { util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); if (ep11->dll_m_rm_module != NULL) { ep11->dll_m_rm_module(NULL, target); } else { /* * With the old target handling, target is a pointer to * ep11_target_t */ free((ep11_target_t *)target); } } /** * Performs an EP11 administrative request to Re-encrypt a single EP11 secure * key with a new EP11 master key (wrapping key). * * @param[in] ep11 the EP11 library structure * @param[in] target the target handle to use for the re-encipher operation * @param[in] card the card that corresponds to the target handle * @param[in] domain the domain that corresponds to the target handle * @param[in/out] ep11key the EP11 key token to reencipher. The re-enciphered * secure key will be returned in this buffer. * @param[in] ep11key_size the size of the secure key * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of errors */ static int ep11_adm_reencrypt(struct ep11_lib *ep11, target_t target, unsigned int card, unsigned int domain, struct ep11keytoken *ep11key, unsigned int ep11key_size, bool verbose) { CK_BYTE resp[MAX_BLOBSIZE]; CK_BYTE req[MAX_BLOBSIZE]; char ep11_token_header[sizeof(ep11key->head)]; struct XCPadmresp lrb; struct XCPadmresp rb; size_t resp_len; size_t blob_len; long req_len; CK_RV rv; int rc; blob_len = ep11key->head.length; if (blob_len > ep11key_size) { pr_verbose(verbose, "Blob length larger than secure key size"); return -EINVAL; } rb.domain = domain; lrb.domain = domain; /* The token header is an overlay over the (all zero) session field */ memcpy(ep11_token_header, ep11key, sizeof(ep11_token_header)); memset(ep11key->session, 0, sizeof(ep11key->session)); resp_len = sizeof(resp); req_len = ep11->dll_xcpa_cmdblock(req, sizeof(req), XCP_ADM_REENCRYPT, &rb, NULL, (unsigned char *)ep11key, blob_len); if (req_len < 0) { pr_verbose(verbose, "Failed to build XCP command block"); return -EIO; } rv = ep11->dll_m_admin(resp, &resp_len, NULL, NULL, req, req_len, NULL, 0, target); if (rv != CKR_OK || resp_len == 0) { pr_verbose(verbose, "Command XCP_ADM_REENCRYPT failed. " "rc = 0x%lx, resp_len = %ld", rv, resp_len); return -EIO; } rc = ep11->dll_xcpa_internal_rv(resp, resp_len, &lrb, &rv); if (rc != 0) { pr_verbose(verbose, "Failed to parse response. rc = %d", rc); return -EIO; } if (rv != CKR_OK) { pr_verbose(verbose, "Failed to re-encrypt the EP11 secure key. " "rc = 0x%lx", rv); switch (rv) { case CKR_IBM_WKID_MISMATCH: DEBUG("The EP11 secure key is currently encrypted " "under a different master that does not match " "the master key in the CURRENT master key " "register of APQN %02X.%04X", card, domain); break; } return -EIO; } if (blob_len != lrb.pllen) { pr_verbose(verbose, "Re-encrypted EP11 secure key size has " "changed: org-len: %lu, new-len: %lu", blob_len, lrb.pllen); return -EIO; } memcpy(ep11key, lrb.payload, blob_len); memcpy(ep11key, ep11_token_header, sizeof(ep11_token_header)); return 0; } /** * Re-encipher an EP11 secure key with a new EP11 master key (wrapping key). * * @param[in] ep11 the EP11 library structure * @param[in] target the target handle to use for the re-encipher operation * @param[in] card the card that corresponds to the target handle * @param[in] domain the domain that corresponds to the target handle * @param[in/out] secure_key the EP11 key token to reencipher. The re-enciphered * secure key will be returned in this buffer. * @param[in] secure_key_size the size of the secure key * @param[in] verbose if true, verbose messages are printed * * @returns 0 on success, a negative errno in case of errors */ int reencipher_ep11_key(struct ep11_lib *ep11, target_t target, unsigned int card, unsigned int domain, u8 *secure_key, unsigned int secure_key_size, bool verbose) { struct ep11keytoken *ep11key = (struct ep11keytoken *)secure_key; CK_IBM_DOMAIN_INFO dinf; CK_ULONG dinf_len = sizeof(dinf); CK_RV rv; int rc; util_assert(ep11 != NULL, "Internal error: ep11 is NULL"); util_assert(secure_key != NULL, "Internal error: secure_key is NULL"); rv = ep11->dll_m_get_xcp_info(&dinf, &dinf_len, CK_IBM_XCPQ_DOMAIN, 0, target); if (rv != CKR_OK) { pr_verbose(verbose, "Failed to query domain information for " "%02X.%04X: m_get_xcp_info rc: 0x%lx", card, domain, rv); return -EIO; } if ((dinf.flags & CK_IBM_DOM_COMMITTED_NWK) == 0) { DEBUG("The NEW master key register of APQN %02X.%04X is not " "in COMMITTED state", card, domain); return -ENODEV; } rc = ep11_adm_reencrypt(ep11, target, card, domain, ep11key, secure_key_size, verbose); if (rc != 0) return rc; if (is_xts_key(secure_key, secure_key_size)) { secure_key += EP11_KEY_SIZE; secure_key_size -= EP11_KEY_SIZE; ep11key = (struct ep11keytoken *)secure_key; rc = ep11_adm_reencrypt(ep11, target, card, domain, ep11key, secure_key_size, verbose); if (rc != 0) return rc; } return 0; } libzpc-1.0.0/src/zkey/ep11.h000066400000000000000000000106501413160260300154610ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * This header file defines the interface to the EP11 host library. * * Copyright IBM Corp. 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef EP11_H #define EP11_H #include #include #include "lib/zt_common.h" /* EP11 definitions */ typedef uint64_t target_t; typedef unsigned long int CK_ULONG; typedef CK_ULONG CK_RV; typedef unsigned char CK_BYTE; typedef CK_BYTE CK_CHAR; typedef CK_ULONG *CK_ULONG_PTR; typedef void *CK_VOID_PTR; typedef struct XCP_ModuleSocket { char host[256 + 1]; uint32_t port; } *XCP_ModuleSocket_t; typedef struct XCP_DomainPerf { unsigned int lastperf[256]; } *XCP_DomainPerf_t; typedef struct XCP_Module { uint32_t version; uint64_t flags; uint32_t domains; unsigned char domainmask[256 / 8]; struct XCP_ModuleSocket socket; uint32_t module_nr; void *mhandle; struct XCP_DomainPerf perf; /* ----- end of v1 fields ----- */ uint32_t api; /* ----- end of v2 fields ----- */ } *XCP_Module_t; typedef enum { XCP_MFL_SOCKET = 1, XCP_MFL_MODULE = 2, XCP_MFL_MHANDLE = 4, XCP_MFL_PERF = 8, XCP_MFL_VIRTUAL = 0x10, XCP_MFL_STRICT = 0x20, XCP_MFL_PROBE = 0x40, XCP_MFL_ALW_TGT_ADD = 0x80, XCP_MFL_MAX = 0xff } XCP_Module_Flags; #define XCP_MOD_VERSION_1 1 #define XCP_MOD_VERSION_2 2 #define XCP_TGT_INIT ~0UL #define XCPTGTMASK_SET_DOM(mask, domain) \ mask[((domain)/8)] |= (1 << (7-(domain)%8)) #define XCP_SERIALNR_CHARS 8 #define XCP_ADMCTR_BYTES ((size_t) (128/8)) #define XCP_KEYCSUM_BYTES (256/8) #define XCP_ADM_REENCRYPT 25 /* transform blobs to next WK */ #define MAX_BLOBSIZE 8192 #define CKR_VENDOR_DEFINED 0x80000000 #define CKR_IBM_WKID_MISMATCH CKR_VENDOR_DEFINED + 0x10001 typedef struct XCPadmresp { uint32_t fn; uint32_t domain; uint32_t domainInst; /* module ID || module instance */ unsigned char module[XCP_SERIALNR_CHARS + XCP_SERIALNR_CHARS]; unsigned char modNr[XCP_SERIALNR_CHARS]; unsigned char modInst[XCP_SERIALNR_CHARS]; unsigned char tctr[XCP_ADMCTR_BYTES]; /* transaction counter */ CK_RV rv; uint32_t reason; const unsigned char *payload; size_t pllen; } *XCPadmresp_t; typedef struct CK_IBM_DOMAIN_INFO { CK_ULONG domain; CK_BYTE wk[XCP_KEYCSUM_BYTES]; CK_BYTE nextwk[XCP_KEYCSUM_BYTES]; CK_ULONG flags; CK_BYTE mode[8]; } CK_IBM_DOMAIN_INFO; #define CK_IBM_DOM_COMMITTED_NWK 8 #define CK_IBM_XCPHQ_VERSION 0xff000001 #define CK_IBM_XCPQ_DOMAIN 3 #define MAX_APQN 256 typedef struct { short format; short length; short apqns[2 * MAX_APQN]; } __packed ep11_target_t; #define CKR_OK 0x00000000 typedef int (*m_init_t) (void); typedef int (*m_add_module_t) (XCP_Module_t module, target_t *target); typedef int (*m_rm_module_t) (XCP_Module_t module, target_t target); typedef CK_RV (*m_get_xcp_info_t)(CK_VOID_PTR pinfo, CK_ULONG_PTR infbytes, unsigned int query, unsigned int subquery, target_t target); typedef unsigned long int (*m_admin_t)(unsigned char *resp1, size_t *r1len, unsigned char *resp2, size_t *r2len, const unsigned char *cmd, size_t clen, const unsigned char *sigs, size_t slen, target_t target); typedef long (*xcpa_cmdblock_t)(unsigned char *blk, size_t blen, unsigned int fn, const struct XCPadmresp *minf, const unsigned char *tctr, const unsigned char *payload, size_t plen); typedef long (*xcpa_internal_rv_t)(const unsigned char *rsp, size_t rlen, struct XCPadmresp *rspblk, CK_RV *rv); struct ep11_version { unsigned int minor; unsigned int major; }; struct ep11_lib { void *lib_ep11; m_init_t dll_m_init; m_add_module_t dll_m_add_module; m_rm_module_t dll_m_rm_module; m_get_xcp_info_t dll_m_get_xcp_info; m_admin_t dll_m_admin; xcpa_cmdblock_t dll_xcpa_cmdblock; xcpa_internal_rv_t dll_xcpa_internal_rv; struct ep11_version version; }; int load_ep11_library(struct ep11_lib *ep11, bool verbose); int get_ep11_target_for_apqn(struct ep11_lib *ep11, unsigned int card, unsigned int domain, target_t *target, bool verbose); void free_ep11_target_for_apqn(struct ep11_lib *ep11, target_t target); int reencipher_ep11_key(struct ep11_lib *ep11, target_t target, unsigned int card, unsigned int domain, u8 *secure_key, unsigned int secure_key_size, bool verbose); #endif libzpc-1.0.0/src/zkey/lib/000077500000000000000000000000001413160260300153065ustar00rootroot00000000000000libzpc-1.0.0/src/zkey/lib/util_base.c000066400000000000000000000111611413160260300174210ustar00rootroot00000000000000/* * util - Utility function library * * General helper functions * * Copyright IBM Corp. 2013, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include "lib/util_base.h" #include "lib/util_libc.h" /* * Print hexdump for buffer with variable group parameter */ void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int grp, int count, int indent) { const char *buf = data; int i, first = 1; for (i = 0; i < count; i++) { if (first) { fprintf(fh, "%*s", indent, " "); if (tag) fprintf(fh, "%s: ", tag); fprintf(fh, "%08x: ", i); first = 0; } fprintf(fh, "%02x", buf[i]); if (i % 16 == 15 || i + 1 == count) { fprintf(fh, "\n"); first = 1; } else if (i % grp == grp - 1) { fprintf(fh, " "); } } } /* * Print hexdump for buffer with fix grp parameter */ void util_hexdump(FILE *fh, const char *tag, const void *data, int count) { util_hexdump_grp(fh, tag, data, sizeof(long), count, 0); } #define MAX_CHARS_PER_LINE 80 /* * Print string with indentation * * Print a string while accounting for a given indent value, characters per line * limit, and line breaks ('\n') within the string. The first line has to be * indented manually. * * @param[in] str String that should be printed * @param[in] indent Indentation for printing */ void util_print_indented(const char *str, int indent) { char *word, *line, *desc, *desc_ptr; int word_len, pos = indent; desc = desc_ptr = util_strdup(str); line = strsep(&desc, "\n"); while (line) { word = strsep(&line, " "); pos = indent; while (word) { word_len = strlen(word); if (pos + word_len + 1 > MAX_CHARS_PER_LINE) { printf("\n%*s", indent, ""); pos = indent; } if (pos == indent) printf("%s", word); else printf(" %s", word); pos += word_len + 1; word = strsep(&line, " "); } if (desc) printf("\n%*s", indent, ""); line = strsep(&desc, "\n"); } printf("\n"); free(desc_ptr); } /** * Determines the absolute name of an s390-tools system directory * (it could be data, or library directory) */ static const char *util_sysdir(const char *env_var, const char *default_dir) { return secure_getenv(env_var) ?: default_dir; } /** * Determines the absolute name of a file installed in the s390-tools * system directory */ static const char *util_sysdir_path(const char *filename, const char *dirname) { static char libdir_pathname[PATH_MAX]; int ret; ret = snprintf(libdir_pathname, sizeof(libdir_pathname), "%s/%s", dirname, filename); if (ret < 0 || ret >= (int)sizeof(libdir_pathname)) errx(EXIT_FAILURE, "Could not compose absolute pathname of %s and %s", dirname, filename); return libdir_pathname; } /** * Determines the absolute name of a s390-tools library directory * * Resources are handled by the library * * @returns Pointer to a buffer, which contains the null-terminated name */ const char *util_libdir(void) { return util_sysdir("S390TOOLS_LIBDIR", TOOLS_LIBDIR); } /** * Determines the absolute name of a file installed in the s390-tools * library directory by its relative name. * * Resources are handled by the library. A second call of this function * overwrites previously returned data. Care must be taken when attempting * to do a second call. * * @param[in] filename Null-terminated file name relative to the s390-tools * library directory * @returns Pointer to a buffer of PATH_MAX size, which contains the * null-terminated absolute name */ const char *util_libdir_path(const char *filename) { return util_sysdir_path(filename, util_libdir()); } /** * Determines the absolute name of a s390-tools data directory * * Resources are handled by the library * * @returns Pointer to a buffer which contains the null-terminated name */ const char *util_datadir(void) { return util_sysdir("S390TOOLS_DATADIR", TOOLS_DATADIR); } /** * Determines the absolute name of a file installed in the s390-tools * data directory by its relative name. * * Resources are handled by the library. A second call of this function * overwrites previously returned data. Care must be taken when attempting * to do a second call. * * @param[in] filename Null-terminated file name relative to the s390-tools * data directory * @returns Pointer to a buffer of PATH_MAX size, which contains the * null-terminated absolute name */ const char *util_datadir_path(const char *filename) { return util_sysdir_path(filename, util_datadir()); } libzpc-1.0.0/src/zkey/lib/util_base.h000066400000000000000000000017231413160260300174310ustar00rootroot00000000000000/* * util - Utility function library * * General helper functions * * Copyright IBM Corp. 2013, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef LIB_UTIL_BASE_H #define LIB_UTIL_BASE_H #include #include #include "zt_common.h" void util_hexdump(FILE *fh, const char *tag, const void *data, int cnt); void util_hexdump_grp(FILE *fh, const char *tag, const void *data, int group, int cnt, int indent); void util_print_indented(const char *str, int indent); const char *util_libdir(void); const char *util_libdir_path(const char *filename); const char *util_datadir(void); const char *util_datadir_path(const char *filename); static inline void util_ptr_vec_free(void **ptr_vec, int count) { int i; if (!ptr_vec || count < 0) return; for (i = 0; i < count; i++) free(ptr_vec[i]); free(ptr_vec); } #endif /* LIB_UTIL_BASE_H */ libzpc-1.0.0/src/zkey/lib/util_file.c000066400000000000000000000303301413160260300174250ustar00rootroot00000000000000/* * util - Utility function library * * Read and write files * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include #include #include #include #include "lib/util_base.h" #include "lib/util_file.h" #include "lib/util_libc.h" #include "lib/util_panic.h" #include "lib/util_prg.h" /* * Read the first line of a file into given buffer */ static int file_gets(char *str, size_t size, const char *path) { char *p, *end; FILE *fp; int rc; /* In case of error we always return empty string */ str[0] = 0; /* Read the string */ fp = fopen(path, "r"); if (!fp) return -1; p = fgets(str, size, fp); if (p) { /* Check for end of line */ end = memchr(str, '\n', size); if (end) *end = 0; else str[size - 1] = 0; } if (strlen(str) == 0) { rc = -1; goto out_fclose; } rc = 0; out_fclose: fclose(fp); return rc; } /** * Read the first line of a file * * If read is successful 'str' contains first line of a file without the * trailing newline. If read fails, an empty string is returned for 'str' * The resulting string will always be null-terminated. * * @param[out] str Result buffer * @param[in] size Size of the result buffer * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 File was read * @retval -1 Error while reading file */ int util_file_read_line(char *const str, size_t size, const char *fmt, ...) { char path[PATH_MAX]; va_list ap; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); return file_gets(str, size, path); } /* * Write string to a file */ static int file_puts(const char *str, const char *path) { FILE *fp; int rc; /* write the string */ fp = fopen(path, "w"); if (!fp) return -1; if (fputs(str, fp) == EOF) { rc = -1; goto out_fclose; } rc = 0; out_fclose: fclose(fp); return rc; } /** * Write string to a file without the terminating null byte * * @param[in] str Content is to be written * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Write was successful * @retval -1 Error while writing file */ int util_file_write_s(const char *str, const char *fmt, ...) { char path[PATH_MAX]; va_list ap; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); return file_puts(str, path); } /** * Write signed long value to a file according to given base * * @param[in] val Value is to be written * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Write was successful * @retval -1 Error while writing file */ int util_file_write_l(long val, int base, const char *fmt, ...) { char *str, path[PATH_MAX]; va_list ap; int rc; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); switch (base) { case 8: util_asprintf(&str, "%lo", val); break; case 10: util_asprintf(&str, "%ld", val); break; case 16: util_asprintf(&str, "%lx", val); break; default: util_panic("Invalid base: %d\n", base); } rc = file_puts(str, path); free(str); return rc; } /** * Write signed long long value to a file according to given base * * @param[in] val Value is to be written * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Write was successful * @retval -1 Error while writing file */ int util_file_write_ll(long long val, int base, const char *fmt, ...) { char *str, path[PATH_MAX]; va_list ap; int rc; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); switch (base) { case 8: util_asprintf(&str, "%llo", val); break; case 10: util_asprintf(&str, "%lld", val); break; case 16: util_asprintf(&str, "%llx", val); break; default: util_panic("Invalid base: %d\n", base); } rc = file_puts(str, path); free(str); return rc; } /** * Write unsigned long value to a file according to given base * * @param[in] val Value is to be written * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Write was successful * @retval -1 Error while writing file */ int util_file_write_ul(unsigned long val, int base, const char *fmt, ...) { char *str, path[PATH_MAX]; va_list ap; int rc; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); switch (base) { case 8: util_asprintf(&str, "%lo", val); break; case 10: util_asprintf(&str, "%lu", val); break; case 16: util_asprintf(&str, "%lx", val); break; default: util_panic("Invalid base: %d\n", base); } rc = file_puts(str, path); free(str); return rc; } /** * Write unsigned long long value to a file according to given base * * @param[in] val Value is to be written * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Write was successful * @retval -1 Error while writing file */ int util_file_write_ull(unsigned long long val, int base, const char *fmt, ...) { char *str, path[PATH_MAX]; va_list ap; int rc; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); switch (base) { case 8: util_asprintf(&str, "%llo", val); break; case 10: util_asprintf(&str, "%llu", val); break; case 16: util_asprintf(&str, "%llx", val); break; default: util_panic("Invalid base: %d\n", base); } rc = file_puts(str, path); free(str); return rc; } /** * Read a file and convert it to signed int according to given base * * @param[out] val Buffer for value * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Integer has been read correctly * @retval -1 Error while reading file */ int util_file_read_i(int *val, int base, const char *fmt, ...) { char path[PATH_MAX], buf[512]; va_list ap; int count; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); if (file_gets(buf, sizeof(buf), path)) return -1; switch (base) { case 8: count = sscanf(buf, "%do", val); break; case 10: count = sscanf(buf, "%dd", val); break; case 16: count = sscanf(buf, "%dx", val); break; default: util_panic("Invalid base: %d\n", base); } return (count == 1) ? 0 : -1; } /** * Read a file and convert it to signed long according to given base * * @param[out] val Buffer for value * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Long integer has been read correctly * @retval -1 Error while reading file */ int util_file_read_l(long *val, int base, const char *fmt, ...) { char path[PATH_MAX], buf[512]; va_list ap; int count; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); if (file_gets(buf, sizeof(buf), path)) return -1; switch (base) { case 8: count = sscanf(buf, "%lo", val); break; case 10: count = sscanf(buf, "%ld", val); break; case 16: count = sscanf(buf, "%lx", val); break; default: util_panic("Invalid base: %d\n", base); } return (count == 1) ? 0 : -1; } /** * Read a file and convert it to signed long long according to given base * * @param[out] val Buffer for value * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Long integer has been read correctly * @retval -1 Error while reading file */ int util_file_read_ll(long long *val, int base, const char *fmt, ...) { char path[PATH_MAX], buf[512]; va_list ap; int count; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); if (file_gets(buf, sizeof(buf), path)) return -1; switch (base) { case 8: count = sscanf(buf, "%llo", val); break; case 10: count = sscanf(buf, "%lld", val); break; case 16: count = sscanf(buf, "%llx", val); break; default: util_panic("Invalid base: %d\n", base); } return (count == 1) ? 0 : -1; } /** * Read a file and convert it to unsigned int according to given base * * @param[out] val Buffer for value * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Integer has been read correctly * @retval -1 Error while reading file */ int util_file_read_ui(unsigned int *val, int base, const char *fmt, ...) { char path[PATH_MAX], buf[512]; va_list ap; int count; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); if (file_gets(buf, sizeof(buf), path)) return -1; switch (base) { case 8: count = sscanf(buf, "%uo", val); break; case 10: count = sscanf(buf, "%uu", val); break; case 16: count = sscanf(buf, "%ux", val); break; default: util_panic("Invalid base: %d\n", base); } return (count == 1) ? 0 : -1; } /** * Read a file and convert it to unsigned long according to given base * * @param[out] val Buffer for value * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Long integer has been read correctly * @retval -1 Error while reading file */ int util_file_read_ul(unsigned long *val, int base, const char *fmt, ...) { char path[PATH_MAX], buf[512]; va_list ap; int count; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); if (file_gets(buf, sizeof(buf), path)) return -1; switch (base) { case 8: count = sscanf(buf, "%lo", val); break; case 10: count = sscanf(buf, "%lu", val); break; case 16: count = sscanf(buf, "%lx", val); break; default: util_panic("Invalid base: %d\n", base); } return (count == 1) ? 0 : -1; } /** * Read a file and convert it to unsigned long long according to given base * * @param[out] val Buffer for value * @param[in] base Base for conversion, either 8, 10, or 16 * @param[in] fmt Format string for generation of the path name * @param[in] ... Parameters for format string * * @retval 0 Long integer has been read correctly * @retval -1 Error while reading file */ int util_file_read_ull(unsigned long long *val, int base, const char *fmt, ...) { char path[PATH_MAX], buf[512]; va_list ap; int count; /* Construct the file name */ UTIL_VSPRINTF(path, fmt, ap); if (file_gets(buf, sizeof(buf), path)) return -1; switch (base) { case 8: count = sscanf(buf, "%llo", val); break; case 10: count = sscanf(buf, "%llu", val); break; case 16: count = sscanf(buf, "%llx", val); break; default: util_panic("Invalid base: %d\n", base); } return (count == 1) ? 0 : -1; } /** * Read a file and convert it according to format string * * @param[in] path File name to read * @param[in] fmt Format string for parsing the content * @param[out] ... Parameters for format string * * @retval != -1 Number of values parsed correctly * @retval -1 Error while reading file */ int util_file_read_va(const char *path, const char *fmt, ...) { char buf[512]; va_list ap; int ret; if (file_gets(buf, sizeof(buf), path)) return -1; va_start(ap, fmt); ret = vsscanf(buf, fmt, ap); va_end(ap); if (ret == EOF) return -1; return ret; } libzpc-1.0.0/src/zkey/lib/util_file.h000066400000000000000000000024061413160260300174350ustar00rootroot00000000000000/** * @defgroup util_file_h util_file: File read/write interface * @{ * @brief Read and write files * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef LIB_UTIL_FILE_H #define LIB_UTIL_FILE_H int util_file_read_line(char *str, size_t size, const char *fmt, ...); int util_file_read_i(int *val, int base, const char *fmt, ...); int util_file_read_l(long *val, int base, const char *fmt, ...); int util_file_read_ll(long long *val, int base, const char *fmt, ...); int util_file_read_ui(unsigned int *val, int base, const char *fmt, ...); int util_file_read_ul(unsigned long *val, int base, const char *fmt, ...); int util_file_read_ull(unsigned long long *val, int base, const char *fmt, ...); int util_file_write_s(const char *str, const char *fmt, ...); int util_file_write_l(long val, int base, const char *fmt, ...); int util_file_write_ll(long long val, int base, const char *fmt, ...); int util_file_write_ul(unsigned long val, int base, const char *fmt, ...); int util_file_write_ull(unsigned long long val, int base, const char *fmt, ...); int util_file_read_va(const char *path, const char *fmt, ...); #endif /** LIB_UTIL_FILE_H @} */ libzpc-1.0.0/src/zkey/lib/util_libc.c000066400000000000000000000122211413160260300174160ustar00rootroot00000000000000/* * util - Utility function library * * Handle standard errors for libc functions * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include "lib/util_base.h" #include "lib/util_libc.h" #include "lib/util_panic.h" /* * Return size as string of largest unit, e.g. 1025 = "1 KiB" */ static void format_size(char *str, size_t size) { static const char * const unit_vec[] = {"byte", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"}; unsigned int i; for (i = 0; i < ARRAY_SIZE(unit_vec); i++) { if (size / 1024 == 0) { sprintf(str, "%zu %s", size, unit_vec[i]); return; } size /= 1024; } sprintf(str, "huge"); } static void __util_oom(const char *func, const char *file, int line, size_t size) { char size_str[256]; fprintf(stderr, "%s: Failed to allocate memory", program_invocation_short_name); if (size > 0) { format_size(size_str, size); fprintf(stderr, " (%s)", size_str); } fprintf(stderr, " at %s:%d %s()\n", file, line, func); exit(EXIT_FAILURE); } /* * Allocate memory or exit in case of failure */ void *__util_malloc(const char *func, const char *file, int line, size_t size) { void *buf; buf = malloc(size); if (buf == NULL) __util_oom(func, file, line, size); return buf; } /* * Allocate zero-initialized memory or exit in case of failure */ void *__util_zalloc(const char *func, const char *file, int line, size_t size) { void *buf = __util_malloc(func, file, line, size); memset(buf, 0, size); return buf; } /* * Re-allocate memory or exit in case of failure */ void *__util_realloc(const char *func, const char *file, int line, void *ptr, size_t size) { void *buf; buf = realloc(ptr, size); if (buf == NULL) __util_oom(func, file, line, size); return buf; } /* * Duplicate a string buffer or exit in case of failure */ void *__util_strdup(const char *func, const char *file, int line, const char *str) { void *buf = strdup(str); if (buf == NULL) __util_oom(func, file, line, strlen(str) + 1); return buf; } /** * Concatenate two strings or exit in case of failure * * The first string \a str1 is resized and a copy of the second * string \a str2 is appended to it. * * Therefore the first string \a str1 must either have been allocated * using malloc(), calloc(), or realloc() or must be NULL. * * @param[in] str1 Pointer to first string to concatenate, which * becomes invalid * @param[in] str2 Constant pointer to second string to concatenate * * @returns Pointer to concatenated string */ char *util_strcat_realloc(char *str1, const char *str2) { char *buf; if (str1) { buf = util_realloc(str1, strlen(str1) + strlen(str2) + 1); strcat(buf, str2); } else { buf = util_strdup(str2); } return buf; } /** * Convert string to uppercase * * String \a str is converted to uppercase * * @param[in,out] str String to convert */ void util_str_toupper(char *str) { int i; for (i = 0; str[i] != '\0'; i++) str[i] = toupper(str[i]); } /* * Print to newly allocated string or exit in case of failure */ int __util_vasprintf(const char *func, const char *file, int line, char **strp, const char *fmt, va_list ap) { int rc; rc = vasprintf(strp, fmt, ap); if (rc == -1) __util_oom(func, file, line, 0); return rc; } /* * Print to newly allocated string or exit in case of failure */ int __util_asprintf(const char *func, const char *file, int line, char **strp, const char *fmt, ...) { va_list ap; int rc; va_start(ap, fmt); rc = __util_vasprintf(func, file, line, strp, fmt, ap); va_end(ap); return rc; } /* * Print to string buffer or exit in case of failure */ int __util_vsprintf(const char *func, const char *file, int line, char *str, const char *fmt, va_list ap) { int rc; rc = vsprintf(str, fmt, ap); if (rc == -1) __util_assert("rc != -1", func, file, line, rc != -1, "Could not format string\n"); return rc; } /** * Strip leading and trailing spaces from string * * Remove string \a s leading and trailing spaces * * @param[in,out] s String to manipulate * * @returns Pointer to first non-space character in string \a s */ char *util_strstrip(char *s) { size_t size; char *end; size = strlen(s); if (!size) return s; end = s + size - 1; while (end >= s && isspace(*end)) end--; *(end + 1) = '\0'; while (*s && isspace(*s)) s++; return s; } /** * Copy \a src to buffer \a dest of size \a size. At most size - 1 * chars will be copied. \a dest will always be NUL terminated. * * Note: If the return value is greater than or equal to size truncation * occurred. * * @param[in] dest Destination buffer * @param[in] src Source string * @param[in] size Size of destination buffer * * @returns strlen Length of \a src string */ size_t util_strlcpy(char *dest, const char *src, size_t size) { size_t str_len = strlen(src); size_t len; if (size) { len = MIN(size - 1, str_len); memcpy(dest, src, len); dest[len] = '\0'; } return str_len; } libzpc-1.0.0/src/zkey/lib/util_libc.h000066400000000000000000000075021413160260300174310ustar00rootroot00000000000000/** * @defgroup util_libc_h util_libc: Libc wrapper interface * @{ * @brief Handle standard errors for libc functions * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef LIB_UTIL_LIBC_H #define LIB_UTIL_LIBC_H #include #ifdef __cplusplus extern "C" { #endif /** * Allocate memory or panic in case of failure * * @param[in] size Number of bytes to be allocated * * @returns Pointer to memory buffer created with malloc() */ #define util_malloc(size) \ __util_malloc(__func__, __FILE__, __LINE__, size) void *__util_malloc(const char *func, const char *file, int line, size_t size); /** * Allocate zero-initialized memory or panic in case of failure * * @param[in] size Number of bytes to be allocated * * @returns Pointer to memory buffer created with calloc() */ #define util_zalloc(size) \ __util_zalloc(__func__, __FILE__, __LINE__, size) void *__util_zalloc(const char *func, const char *file, int line, size_t size); /** * Re-allocate memory or exit in case of failure * * @param[in] ptr Pointer ot old memory buffer * @param[in] size Number of bytes to be allocated * * @returns Pointer to memory buffer created with realloc() */ #define util_realloc(ptr, size) \ __util_realloc(__func__, __FILE__, __LINE__, ptr, size) void *__util_realloc(const char *func, const char *file, int line, void *ptr, size_t size); /** * Duplicate a string buffer or exit in case of failure * * @param[in] str String to be duplicated * * @returns Pointer to copied string allocated with malloc() */ #define util_strdup(str) \ __util_strdup(__func__, __FILE__, __LINE__, str) void *__util_strdup(const char *func, const char *file, int line, const char *str); /** * Print to allocated string or exit in case of failure * * @param[in,out] strp Pointer for returned string allocated with malloc() * @param[in] fmt Format string for generation of string * @param[in] ap Parameters for format string * * @returns num Number of formatted characters */ #define util_vasprintf(strp, fmt, ap) \ __util_vasprintf(__func__, __FILE__, __LINE__, strp, fmt, ap) #define UTIL_VASPRINTF(strp, fmt, ap) \ do { \ va_start(ap, fmt); \ util_vasprintf(strp, fmt, ap); \ va_end(ap); \ } while (0) int __util_vasprintf(const char *func, const char *file, int line, char **strp, const char *fmt, va_list ap); /** * Print to newly allocated string or exit in case of failure * * @param[in,out] strp Pointer for returned string allocated with malloc() * @param[in] ... Format string and parameters for format string * * @returns num Number of formatted characters */ #define util_asprintf(strp, ...) \ __util_asprintf(__func__, __FILE__, __LINE__, strp, ##__VA_ARGS__) int __util_asprintf(const char *func, const char *file, int line, char **strp, const char *fmt, ...); /** * Print to string buffer or exit in case of failure * * @param[in] str String buffer * @param[in] fmt Format string for generation of string * @param[in] ap Parameters for format string * * @returns num Number of formatted characters */ #define util_vsprintf(str, fmt, ap) \ __util_vsprintf(__func__, __FILE__, __LINE__, str, fmt, ap) #define UTIL_VSPRINTF(str, fmt, ap) \ do { \ va_start(ap, fmt); \ util_vsprintf(str, fmt, ap); \ va_end(ap); \ } while (0) int __util_vsprintf(const char *func, const char *file, int line, char *str, const char *fmt, va_list ap); char *util_strcat_realloc(char *str1, const char *str2); void util_str_toupper(char *str); char *util_strstrip(char *s); size_t util_strlcpy(char *dest, const char *src, size_t size); #ifdef __cplusplus } #endif #endif /** LIB_UTIL_LIBC_H @} */ libzpc-1.0.0/src/zkey/lib/util_panic.c000066400000000000000000000060041413160260300176010ustar00rootroot00000000000000/* * util - Utility function library * * Collect FFDC data for unexpected errors * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "debug.h" #include #include #include #include #include #include #include "lib/util_base.h" #include "lib/util_panic.h" /* * Obtain a backtrace and print it to stderr * * To get symbols, compile the code with "-rdynamic". */ static void print_backtrace(void) { void *array[256]; size_t i, size; char **strings; fprintf(stderr, "Backtrace:\n\n"); size = backtrace(array, ARRAY_SIZE(array)); strings = backtrace_symbols(array, size); if (strings == NULL) { fprintf(stderr, " Could not obtain backtrace (ENOMEM)\n"); return; } for (i = 0; i < size; i++) fprintf(stderr, " %s\n", strings[i]); free(strings); } /* * Check for core ulimit */ static void ulimit_core_check(void) { struct rlimit limit; if (getrlimit(RLIMIT_CORE, &limit) != 0) return; if (limit.rlim_cur != 0) return; fprintf(stderr, "Core dump size is zero. To get a full core dump use 'ulimit -c unlimited'.\n"); } /* * Print FFDC data and then abort */ static void panic_finish(const char *func, const char *file, int line, const char *fmt, va_list ap) { /* Write panic error string */ fprintf(stderr, "\n"); fprintf(stderr, "Error string:\n"); fprintf(stderr, "\n"); fprintf(stderr, " "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); /* Write file, line number, and function name */ fprintf(stderr, "Location:\n\n"); fprintf(stderr, " %s:%d: %s()\n", file, line, func); fprintf(stderr, "\n"); /* Print the function backtrace */ print_backtrace(); fprintf(stderr, "\n"); ulimit_core_check(); fprintf(stderr, "----------------------------------------------------------------------->8-----\n"); abort(); } /* * Do panic processing if the assumption is not true */ void __util_assert(const char *assertion_str, const char *func, const char *file, int line, int assumption, const char *fmt, ...) { va_list ap; if (assumption || debug == 0) return; va_start(ap, fmt); fprintf(stderr, "---8<-------------------------------------------------------------------------\n"); fprintf(stderr, "ASSERTION FAILED: The application terminated due to an internal or OS error\n"); fprintf(stderr, "\n"); fprintf(stderr, "The following assumption was *not* true:\n"); fprintf(stderr, "\n"); fprintf(stderr, " %s\n", assertion_str); panic_finish(func, file, line, fmt, ap); } /* * Do panic processing */ void __noreturn __util_panic(const char *func, const char *file, int line, const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "---8<-------------------------------------------------------------------------\n"); fprintf(stderr, "PANIC: The application terminated due to an unrecoverable error\n"); panic_finish(func, file, line, fmt, ap); while(1); } libzpc-1.0.0/src/zkey/lib/util_panic.h000066400000000000000000000024451413160260300176130ustar00rootroot00000000000000/** * @defgroup util_panic_h util_panic: Panic interface * @{ * @brief Collect FFDC data for unexpected errors * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef LIB_UTIL_PANIC_H #define LIB_UTIL_PANIC_H #include "zt_common.h" /** * Write message, print backtrace and then call the abort() function * * @param[in] ... Format string and parameters describing the panic reason */ #define util_panic(...) \ __util_panic(__func__, __FILE__, __LINE__, ##__VA_ARGS__) void __noreturn __util_panic(const char *func, const char *file, int line, const char *fmt, ...); /** * Ensure that assumption is not true, otherwise panic * * Example: util_assert(ptr == NULL, "The ptr must be NULL, but is %p", ptr) * * @param[in] assumption This assumption has to be true * @param[in] ... Format string and parameters describing the assumption */ #define util_assert(assumption, ...) \ __util_assert(#assumption, __func__, __FILE__, __LINE__, \ assumption, ##__VA_ARGS__) void __util_assert(const char *assertion_string, const char *func, const char *file, int line, int assumption, const char *fmt, ...); #endif /** LIB_UTIL_PANIC_H @} */ libzpc-1.0.0/src/zkey/lib/util_part.c000066400000000000000000000162011413160260300174550ustar00rootroot00000000000000/* * util - Utility function library * * Partition detection functions * * Copyright IBM Corp. 2013, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include #include #include #include "lib/util_part.h" #define GPT_SIGNATURE 0x4546492050415254ULL /* EFI PART */ #define MBR_SIGNATURE 0x55aa #define MBR_PART_TYPE_DOS_EXT 0x05 /* DOS extended partition */ #define MBR_PART_TYPE_WIN98_EXT 0x0f /* Windows 98 extended partition */ #define MBR_PART_TYPE_LINUX_EXT 0x85 /* Linux extended partition */ #define MBR_PART_TYPE_GPT 0xee /* GPT partition */ #define MBR_EXT_PART_NUM_FIRST 5 /* Partition number for first logical vol */ /* * MBR/MSDOS partition entry */ struct mbr_part_entry { uint8_t status; uint8_t chs_start[3]; uint8_t type; uint8_t chs_end[3]; uint32_t blk_start; uint32_t blk_cnt; } __attribute__((packed)); /* * Master Boot Record (MBR) */ struct mbr { uint8_t reserved[0x1be]; struct mbr_part_entry part_entry_vec[4]; uint16_t signature; } __attribute__((packed)); /* * GUID Partition Table (GPT) header */ struct gpt { uint64_t signature; uint32_t version; uint32_t hdr_size; uint32_t hdr_crc; uint32_t reserved1; uint64_t blk_cur; uint64_t blk_back; uint64_t blk_first; uint64_t blk_last; uint8_t guid[16]; uint64_t part_tab_blk_start; uint32_t part_tab_cnt; uint32_t part_tab_entry_size; uint32_t part_tab_crc; } __attribute__((packed)); /* * GPT partition entry */ struct gpt_part_entry { uint8_t type[16]; uint8_t guid[16]; uint64_t blk_start; uint64_t blk_end; uint64_t attr; char name[72]; } __attribute__((packed)); /* * Check for extended partition */ static int mbr_part_is_ext(uint8_t type) { if ((type == MBR_PART_TYPE_DOS_EXT) || (type == MBR_PART_TYPE_WIN98_EXT) || (type == MBR_PART_TYPE_LINUX_EXT)) return 1; return 0; } /* * Check if disk has a classic MBR partion table */ static int mbr_table_valid(struct mbr *mbr) { return mbr->signature == MBR_SIGNATURE; } /* * Search partition in logical volumes of an extended partition */ static int mbr_table_ext_search(int fh, size_t blk_start_mbr, size_t blk_start, size_t blk_cnt, size_t blk_size, int part_num) { size_t start, cnt, start_next; struct mbr mbr; /* Read MBR for logical volume */ if (lseek(fh, blk_start_mbr * blk_size, SEEK_SET) == (off_t)-1) return -1; if (read(fh, &mbr, sizeof(mbr)) == -1) return -1; /* Check for invalid MBR or last entry */ if (mbr.signature != MBR_SIGNATURE) return -1; if (mbr.part_entry_vec[0].blk_start == 0) return -1; /* First entry contains a relative offset for current logical volume */ start = blk_start_mbr + le32toh(mbr.part_entry_vec[0].blk_start); cnt = le32toh(mbr.part_entry_vec[0].blk_cnt); if ((start == blk_start) && (cnt == blk_cnt)) return part_num; /* Second entry contains relative offset for next logical volume */ start_next = le32toh(mbr.part_entry_vec[1].blk_start); if (start_next == 0) return 0; start_next += blk_start_mbr; /* Recursively search for next logical volume in chain */ return mbr_table_ext_search(fh, start_next, blk_start, blk_cnt, blk_size, part_num + 1); } /* * Search partition in MBR partition table */ static int mbr_table_search(int fh, struct mbr *mbr, size_t blk_start, size_t blk_cnt, size_t blk_size, int *part_ext) { int part_num_ext, part_num; size_t start, cnt; uint8_t type; for (part_num = 1; part_num <= 4; part_num++) { type = mbr->part_entry_vec[part_num - 1].type; start = le32toh(mbr->part_entry_vec[part_num - 1].blk_start); cnt = le32toh(mbr->part_entry_vec[part_num - 1].blk_cnt); if (start == 0) /* Empty slot */ continue; /* * The kernel sets count for extended partitions explicitly. * Therefore we do not check count here. */ if (mbr_part_is_ext(type) && (start == blk_start)) { *part_ext = 1; return part_num; } if ((start == blk_start) && (cnt == blk_cnt)) return part_num; if (!mbr_part_is_ext(type)) continue; part_num_ext = mbr_table_ext_search(fh, start, blk_start, blk_cnt, blk_size, MBR_EXT_PART_NUM_FIRST); if (part_num_ext != 0) return part_num_ext; } return 0; } /* * Search partition in GPT partition table */ static int gpt_table_search(int fh, struct gpt *gpt, size_t blk_start, size_t blk_cnt, size_t blk_size) { size_t start, end, part_tab_blk_start, blk_end; uint32_t part_tab_cnt, part_tab_entry_size; struct gpt_part_entry *part_entry; unsigned int part_num; blk_end = blk_start + blk_cnt - 1; part_tab_entry_size = le32toh(gpt->part_tab_entry_size); part_tab_cnt = le32toh(gpt->part_tab_cnt); part_tab_blk_start = le64toh(gpt->part_tab_blk_start); if (lseek(fh, part_tab_blk_start * blk_size, SEEK_SET) == (off_t)-1) return -1; for (part_num = 1; part_num <= part_tab_cnt; part_num++) { char buf[part_tab_entry_size]; part_entry = (struct gpt_part_entry *) buf; if (read(fh, buf, sizeof(buf)) == -1) return -1; start = le64toh(part_entry->blk_start); end = le64toh(part_entry->blk_end); if (start == 0) /* Empty slot */ continue; if ((start == blk_start) && (end == blk_end)) return part_num; } return 0; } /* * Check if disk has a GPT partition table */ static int gpt_table_valid(struct gpt *gpt, struct mbr *mbr) { int cnt, part_num; uint32_t start; uint8_t type; if (gpt->signature != GPT_SIGNATURE) return 0; /* Check for protective MBR (one reserved GPT partition) */ for (part_num = 1, cnt = 0; part_num <= 4; part_num++) { start = le32toh(mbr->part_entry_vec[part_num - 1].blk_start); type = mbr->part_entry_vec[part_num - 1].type; if (!start) continue; if (type != MBR_PART_TYPE_GPT) return 0; if (++cnt > 1) return 0; } return 1; } /* * Search for partition with given start block and count * * Return partition number when found, 0 when not found, and on error -1 * Set "part_ext" to 1 for extended partitions otherwise to 0. */ int util_part_search_fh(int fh, size_t blk_start, size_t blk_cnt, size_t blk_size, int *part_ext) { struct gpt gpt; struct mbr mbr; if (lseek(fh, 0, SEEK_SET) == (off_t)-1) return -1; if (read(fh, &mbr, sizeof(mbr)) == -1) return -1; if (lseek(fh, blk_size, SEEK_SET) == (off_t)-1) return -1; if (read(fh, &gpt, sizeof(gpt)) == -1) return -1; *part_ext = 0; if (gpt_table_valid(&gpt, &mbr)) return gpt_table_search(fh, &gpt, blk_start, blk_cnt, blk_size); if (mbr_table_valid(&mbr)) return mbr_table_search(fh, &mbr, blk_start, blk_cnt, blk_size, part_ext); return -1; } /* * Search for partition with given start block and count * * Return partition number when found, 0 when not found, and on error -1 * Set "part_ext" to 1 for extended partitions otherwise to 0. */ int util_part_search(const char *device, size_t blk_start, size_t blk_cnt, size_t blk_size, int *part_ext) { int rc, fh; fh = open(device, O_RDONLY); if (fh == -1) return -1; rc = util_part_search_fh(fh, blk_start, blk_cnt, blk_size, part_ext); close(fh); return rc; } libzpc-1.0.0/src/zkey/lib/util_part.h000066400000000000000000000010451413160260300174620ustar00rootroot00000000000000/* * util - Utility function library * * Partition detection functions * * Copyright IBM Corp. 2013, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef LIB_UTIL_PART_H #define LIB_UTIL_PART_H int util_part_search(const char *dev, size_t blk_start, size_t blk_cnt, size_t blk_size, int *ext_part); int util_part_search_fh(int fh, size_t blk_start, size_t blk_cnt, size_t blk_size, int *ext_part); #endif /* LIB_UTIL_PART_H */ libzpc-1.0.0/src/zkey/lib/util_path.c000066400000000000000000000126401413160260300174460ustar00rootroot00000000000000/* * util - Utility function library * * Work with paths * * Copyright IBM Corp. 2016, 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include "lib/util_base.h" #include "lib/util_libc.h" #include "lib/util_path.h" #include "lib/util_prg.h" /* * Verify that directory exists */ static void verify_dir(const char *dir) { struct stat sb; int rc; rc = stat(dir, &sb); if (rc < 0) err(EXIT_FAILURE, "Could not access directory: %s", dir); if (!S_ISDIR(sb.st_mode)) errx(EXIT_FAILURE, "Is not a directory: %s", dir); } /* * Return sysfs mount point * * The caller must free the memory for mount_point. */ static void sys_mount_point(char **mount_point) { char *dir; /* Check the environment variable */ dir = secure_getenv("SYSFS_ROOT"); if (dir) *mount_point = util_strdup(dir); else *mount_point = util_strdup("/sys"); verify_dir(*mount_point); } /** * Construct a sysfs path * * The arguments of the function are used to specify a subdirectory under * sysfs root. * * @param[in] fmt Format string for path * @param[in] ... Variable arguments for format string * * @returns Allocated path */ char *util_path_sysfs(const char *fmt, ...) { char *path, *fmt_path, *sysfs; va_list ap; va_start(ap, fmt); util_vasprintf(&fmt_path, fmt, ap); va_end(ap); sys_mount_point(&sysfs); /* Format and return full sysfs path */ util_asprintf(&path, "%s/%s", sysfs, fmt_path); free(fmt_path); free(sysfs); return path; } /** * Test if path exists and is readable * * This function has the same semantics as "-r path" in bash. * * @param[in] fmt Format string for path to test * @param[in] ... Variable arguments for format string * * @returns true Path exists and is readable * false Otherwise */ bool util_path_is_readable(const char *fmt, ...) { va_list ap; char *path; bool rc; UTIL_VASPRINTF(&path, fmt, ap); rc = access(path, R_OK) == 0; free(path); return rc; } /** * Test if path exists and is writable * * This function has the same semantics as "-w path" in bash. * * @param[in] fmt Format string for path to test * @param[in] ... Variable arguments for format string * * @returns true Path exists and is writable * false Otherwise */ bool util_path_is_writable(const char *fmt, ...) { va_list ap; char *path; bool rc; UTIL_VASPRINTF(&path, fmt, ap); rc = access(path, W_OK) == 0; free(path); return rc; } /** * Test if path exists and is a regular file * * This function has the same semantics as "-f path" in bash. * * @param[in] fmt Format string for path to test * @param[in] ... Variable arguments for format string * * @returns true Path exists and is a regular file * false Otherwise */ bool util_path_is_reg_file(const char *fmt, ...) { bool rc = false; struct stat sb; va_list ap; char *path; UTIL_VASPRINTF(&path, fmt, ap); if (stat(path, &sb) == 0) rc = S_ISREG(sb.st_mode); free(path); return rc; } /** * Test if path exists and is a directory * * This function has the same semantics as "-d path" in bash. * * @param[in] fmt Format string for path to test * @param[in] ... Variable arguments for format string * * @returns true Path exists and is a directory * false Otherwise */ bool util_path_is_dir(const char *fmt, ...) { bool rc = false; struct stat sb; va_list ap; char *path; UTIL_VASPRINTF(&path, fmt, ap); if (stat(path, &sb) == 0) rc = S_ISDIR(sb.st_mode); free(path); return rc; } /** * Test if path to directory or file exists * * This function has the same semantics as "-e path" in bash. * * @param[in] fmt Format string for path to test * @param[in] ... Variable arguments for format string * * @returns true Path exists * false Otherwise */ bool util_path_exists(const char *fmt, ...) { va_list ap; char *path; bool rc; UTIL_VASPRINTF(&path, fmt, ap); rc = access(path, F_OK) == 0; free(path); return rc; } /** * Test if path exists, is a regular file, and permission is read-only * * @param[in] fmt Format string for path to test * @param[in] ... Variable arguments for format string * * @returns true Path exists, is a regular file, and permission does * not allow any write but allows read * false Otherwise */ bool util_path_is_readonly_file(const char *fmt, ...) { bool rc = false; struct stat sb; va_list ap; char *path; UTIL_VASPRINTF(&path, fmt, ap); if (stat(path, &sb) == 0) { rc = S_ISREG(sb.st_mode) && (sb.st_mode & 0222) == 0 && (sb.st_mode & 0444) != 0; } free(path); return rc; } /** * Test if path exists, is a regular file, and permission is write-only * * @param[in] fmt Format string for path to test * @param[in] ... Variable arguments for format string * * @returns true Path exists, is a regular file, and permission does * not allow any read but allows write * false Otherwise */ bool util_path_is_writeonly_file(const char *fmt, ...) { bool rc = false; struct stat sb; va_list ap; char *path; UTIL_VASPRINTF(&path, fmt, ap); if (stat(path, &sb) == 0) { rc = S_ISREG(sb.st_mode) && (sb.st_mode & 0222) != 0 && (sb.st_mode & 0444) == 0; } free(path); return rc; } libzpc-1.0.0/src/zkey/lib/util_path.h000066400000000000000000000014031413160260300174460ustar00rootroot00000000000000/** * @defgroup util_path_h util_path: Path interface * @{ * @brief Work with paths * * Copyright IBM Corp. 2016, 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef LIB_UTIL_PATH_H #define LIB_UTIL_PATH_H #include char *util_path_sysfs(const char *fmt, ...); bool util_path_is_readable(const char *fmt, ...); bool util_path_is_writable(const char *fmt, ...); bool util_path_is_dir(const char *fmt, ...); bool util_path_is_reg_file(const char *fmt, ...); bool util_path_exists(const char *fmt, ...); bool util_path_is_readonly_file(const char *fmt, ...); bool util_path_is_writeonly_file(const char *fmt, ...); #endif /** LIB_UTIL_PATH_H @} */ libzpc-1.0.0/src/zkey/lib/util_prg.c000066400000000000000000000057701413160260300173100ustar00rootroot00000000000000/* * util - Utility function library * * Print standard program messages * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include "lib/util_base.h" #include "lib/util_prg.h" #include "lib/zt_common.h" /* * Private data */ static struct util_prg_l { const struct util_prg *prg; /* Command used for parsing */ const char *command; } l; /** * Set the current command for command line option processing * * @param[in] command The current command or NULL for no command */ void util_prg_set_command(const char *command) { l.command = command; } /** * Print program usage information for the --help option */ void util_prg_print_help(void) { /* Print usage */ printf("Usage: %s", program_invocation_short_name); if (l.prg->command_args) printf(" %s", l.prg->command_args); printf(" [OPTIONS]"); if (l.prg->args) printf(" %s", l.prg->args); /* Print usage description */ printf("\n\n"); util_print_indented(l.prg->desc, 0); printf("\n"); } /** * Print program version information for the --version option */ void util_prg_print_version(void) { const struct util_prg_copyright *copyright; printf("%s version %s\n", program_invocation_short_name, RELEASE_STRING); copyright = l.prg->copyright_vec; while (copyright->owner) { if (copyright->pub_first == copyright->pub_last) printf("Copyright %s %d\n", copyright->owner, copyright->pub_first); else printf("Copyright %s %d, %d\n", copyright->owner, copyright->pub_first, copyright->pub_last); copyright++; } } /* * Ask user to use the --help option */ void util_prg_print_parse_error(void) { if (l.command) fprintf(stderr, "Try '%s %s --help' for more information.\n", program_invocation_short_name, l.command); else fprintf(stderr, "Try '%s --help' for more information.\n", program_invocation_short_name); } /** * An option has been specified that is not supported * * @param[in] option Option string (short or long) */ void util_prg_print_invalid_option(const char *opt_name) { fprintf(stderr, "%s: Invalid option '%s'\n", program_invocation_short_name, opt_name); util_prg_print_parse_error(); } /** * A required argument for an option is missing * * @param[in] option Option string */ void util_prg_print_required_arg(const char *opt_name) { fprintf(stderr, "%s: Option '%s' requires an argument\n", program_invocation_short_name, opt_name); util_prg_print_parse_error(); } /** * A superfluous invalid positional argument has been specified * * @param[in] arg_name Name of the invalid argument */ void util_prg_print_arg_error(const char *arg_name) { fprintf(stderr, "%s: Invalid argument '%s'\n", program_invocation_short_name, arg_name); util_prg_print_parse_error(); } /** * Initialize the program module * * @param[in] prg Program description */ void util_prg_init(const struct util_prg *prg) { l.prg = prg; } libzpc-1.0.0/src/zkey/lib/util_prg.h000066400000000000000000000025761413160260300173160ustar00rootroot00000000000000/** * @defgroup util_prg_h util_prg: Program interface * @{ * @brief Print standard program messages * * Copyright IBM Corp. 2016, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef LIB_UTIL_PRG_H #define LIB_UTIL_PRG_H #include #include #include #include #include struct util_prg_copyright { /** Name of the copyright owner, e.g. IBM */ const char *owner; /** Year of first publishing */ int pub_first; /** Year of last major changes */ int pub_last; }; /** * @brief Coypright end marker */ #define UTIL_PRG_COPYRIGHT_END {NULL, 0, 0} /** * Program description */ struct util_prg { /** Description for help */ const char *desc; /** Command arguments in front of other options */ const char *command_args; /** Positional arguments */ const char *args; /** Copyright list */ struct util_prg_copyright copyright_vec[]; }; void util_prg_init(const struct util_prg *prg); void util_prg_set_command(const char *command); void util_prg_print_parse_error(void); void util_prg_print_required_arg(const char *option); void util_prg_print_invalid_option(const char *option); void util_prg_print_arg_error(const char *arg_name); void util_prg_print_version(void); void util_prg_print_help(void); #endif /** LIB_UTIL_PRG_H @} */ libzpc-1.0.0/src/zkey/lib/zt_common.h000066400000000000000000000045321413160260300174700ustar00rootroot00000000000000/* * s390-tools/include/zt_common.h * common s390-tools definitions. * * Copyright IBM Corp. 2004, 2017 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. * */ #ifndef LIB_ZT_COMMON_H #define LIB_ZT_COMMON_H #include "misc.h" #define STRINGIFY_1(x) #x #define STRINGIFY(x) STRINGIFY_1(x) /* Use this macro to make constant macros usable in both assembler and * C code. * * Usage example: * #define IMAGE_ENTRY _AC(0x10000, UL) */ #ifdef __ASSEMBLER__ #define _AC(X, TYPE) X #else #define _AC(X, TYPE) X##TYPE #endif #ifndef __ASSEMBLER__ #ifdef STATIC_ASSERT #elif defined(__GNUC__) && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ >= 5) # define STATIC_ASSERT(test) _Static_assert((test), "(" #test ") failed"); #else # define STATIC_ASSERT(test) #endif #define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) #define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #define RELEASE_STRING STRINGIFY (S390_TOOLS_RELEASE) #define TOOLS_LIBDIR STRINGIFY (S390_TOOLS_LIBDIR) #define TOOLS_SYSCONFDIR STRINGIFY (S390_TOOLS_SYSCONFDIR) #define TOOLS_BINDIR STRINGIFY (S390_TOOLS_BINDIR) #define TOOLS_DATADIR STRINGIFY (S390_TOOLS_DATADIR) #define __noreturn __attribute__((noreturn)) #define __aligned(x) __attribute__((aligned(x))) #define __may_alias __attribute__((may_alias)) #define __section(x) __attribute__((__section__(#x))) #define __noinline __attribute__((__noinline__)) /* The Linux kernel (in stddef.h) and glibc (sys/cdefs.h) define * __always_inline. Therefore undefine it first to allow the headers * to be included first. */ #undef __always_inline #define __always_inline inline __attribute__((always_inline)) #define __pa32(x) ((uint32_t)(unsigned long)(x)) #define __pa(x) ((unsigned long)(x)) #define barrier() __asm__ __volatile__("": : :"memory") #undef MIN #define MIN(x, y) \ ({ \ __typeof__(x) _x = (x); \ __typeof__(y) _y = (y); \ \ _x < _y ? _x : _y; \ }) #undef MAX #define MAX(x, y) \ ({ \ __typeof__(x) _x = (x); \ __typeof__(y) _y = (y); \ \ _x > _y ? _x : _y; \ }) typedef signed long long s64; typedef signed int s32; typedef signed short int s16; typedef signed char s8; #endif /* __ASSEMBLER__ */ #endif /* LIB_ZT_COMMON_H */ libzpc-1.0.0/src/zkey/pkey.c000066400000000000000000000102511413160260300156530ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * Copyright IBM Corp. 2018 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lib/util_base.h" #include "lib/util_libc.h" #include "lib/util_panic.h" #include "pkey.h" #include "utils.h" /** * Check if the specified key is a CCA AESDATA key token. * * @param[in] key the secure key token * @param[in] key_size the size of the secure key * * @returns true if the key is an CCA AESDATA token type */ bool is_cca_aes_data_key(const u8 *key, size_t key_size) { struct tokenheader *hdr = (struct tokenheader *)key; if (key == NULL || key_size < AESDATA_KEY_SIZE) return false; if (hdr->type != TOKEN_TYPE_CCA_INTERNAL) return false; if (hdr->version != TOKEN_VERSION_AESDATA) return false; return true; } /** * Check if the specified key is a CCA AESCIPHER key token. * * @param[in] key the secure key token * @param[in] key_size the size of the secure key * * @returns true if the key is an CCA AESCIPHER token type */ bool is_cca_aes_cipher_key(const u8 *key, size_t key_size) { struct aescipherkeytoken *cipherkey = (struct aescipherkeytoken *)key; if (key == NULL || key_size < AESCIPHER_KEY_SIZE) return false; if (cipherkey->type != TOKEN_TYPE_CCA_INTERNAL) return false; if (cipherkey->version != TOKEN_VERSION_AESCIPHER) return false; if (cipherkey->length > key_size) return false; if (cipherkey->kms != 0x03) /* key wrapped by master key */ return false; if (cipherkey->kwm != 0x02) /* key wrapped using AESKW */ return false; if (cipherkey->pfv != 0x00 && cipherkey->pfv != 0x01) /* V0 or V1 */ return false; if (cipherkey->adv != 0x01) /* Should have ass. data sect. version 1 */ return false; if (cipherkey->at != 0x02) /* Algorithm: AES */ return false; if (cipherkey->kt != 0x0001) /* Key type: CIPHER */ return false; if (cipherkey->adl != 26) /* Ass. data section length should be 26 */ return false; if (cipherkey->kll != 0) /* Should have no key label */ return false; if (cipherkey->eadl != 0) /* Should have no ext associated data */ return false; if (cipherkey->uadl != 0) /* Should have no user associated data */ return false; if (cipherkey->kufc != 2) /* Should have 2 KUFs */ return false; if (cipherkey->kmfc != 3) /* Should have 3 KMFs */ return false; return true; } /** * Check if the specified key is a EP11 AES key token. * * @param[in] key the secure key token * @param[in] key_size the size of the secure key * * @returns true if the key is an EP11 AES token type */ bool is_ep11_aes_key(const u8 *key, size_t key_size) { struct ep11keytoken *ep11key = (struct ep11keytoken *)key; if (key == NULL || key_size < EP11_KEY_SIZE) return false; if (ep11key->head.type != TOKEN_TYPE_NON_CCA) return false; if (ep11key->head.version != TOKEN_VERSION_EP11_AES) return false; if (ep11key->head.length > key_size) return false; if (ep11key->version != 0x1234) return false; return true; } /** * Check if the specified key is an XTS type key * * @param[in] key the secure key token * @param[in] key_size the size of the secure key * * @returns true if the key is an XTS key type */ bool is_xts_key(const u8 *key, size_t key_size) { if (is_cca_aes_data_key(key, key_size)) { if (key_size == 2 * AESDATA_KEY_SIZE && is_cca_aes_data_key(key + AESDATA_KEY_SIZE, key_size - AESDATA_KEY_SIZE)) return true; } else if (is_cca_aes_cipher_key(key, key_size)) { if (key_size == 2 * AESCIPHER_KEY_SIZE && is_cca_aes_cipher_key(key + AESCIPHER_KEY_SIZE, key_size - AESCIPHER_KEY_SIZE)) return true; } else if (is_ep11_aes_key(key, key_size)) { if (key_size == 2 * EP11_KEY_SIZE && is_ep11_aes_key(key + EP11_KEY_SIZE, key_size - EP11_KEY_SIZE)) return true; } return false; } libzpc-1.0.0/src/zkey/pkey.h000066400000000000000000000251501413160260300156640ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * This header file defines the interface to the pkey kernel module. * It defines a set of IOCTL commands with its associated structures. * * Copyright IBM Corp. 2017, 2018 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef PKEY_H #define PKEY_H #include #include "lib/zt_common.h" #include "cca.h" #include "ep11.h" /* * Definitions for the /dev/pkey kernel module interface */ struct tokenheader { u8 type; u8 res0[3]; u8 version; u8 res1[3]; } __packed; #define TOKEN_TYPE_NON_CCA 0x00 #define TOKEN_TYPE_CCA_INTERNAL 0x01 /* CCA-Internal token versions */ #define TOKEN_VERSION_AESDATA 0x04 #define TOKEN_VERSION_AESCIPHER 0x05 /* Non-CCA token versions */ #define TOKEN_VERSION_PROTECTED_KEY 0x01 #define TOKEN_VERSION_CLEAR_KEY 0x02 #define TOKEN_VERSION_EP11_AES 0x03 struct aesdatakeytoken { u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */ u8 res0[3]; u8 version; /* should be TOKEN_VERSION_AESDATA (0x04) */ u8 res1[1]; u8 flag; /* key flags */ u8 res2[1]; u64 mkvp; /* master key verification pattern */ u8 key[32]; /* key value (encrypted) */ u8 cv[8]; /* control vector */ u16 bitsize; /* key bit size */ u16 keysize; /* key byte size */ u8 tvv[4]; /* token validation value */ } __packed; struct aescipherkeytoken { u8 type; /* TOKEN_TYPE_INTERNAL (0x01) for internal key token */ u8 res0; u16 length; /* length of token */ u8 version; /* should be TOKEN_VERSION_CIPHER (0x05) */ u8 res1[3]; u8 kms; /* key material state, should be 0x03 */ u8 kvptype; /* key verification pattern type */ u8 kvp[16]; /* key verification pattern */ u8 kwm; /* key wrapping method, should be 0x02 */ u8 kwh; /* key wrapping hash algorithm */ u8 pfv; /* payload format version, should be 0x00*/ u8 res2; u8 adv; /* associated data section version */ u8 res3; u16 adl; /* associated data length */ u8 kll; /* length of optional key label */ u8 eadl; /* extended associated data length */ u8 uadl; /* user associated data length */ u8 res4; u16 pl; /* payload bit length */ u8 res5; u8 at; /* algorithm type, should be 0x02 (AES) */ u16 kt; /* key type, should be 0x001 (CIPHER) */ u8 kufc; /* key usage field count */ u16 kuf1; /* key usage field 1 */ u16 kuf2; /* key usage field 2 */ u8 kmfc; /* key management field count */ u16 kmf1; /* key management field 1 */ u16 kmf2; /* key management field 2 */ u16 kmf3; /* key management field 3 */ u8 varpart[80]; /* variable part */ } __packed; struct ep11keytoken { union { u8 session[32]; struct { u8 type; /* TOKEN_TYPE_NON_CCA (0x00) */ u8 res0; /* unused */ u16 length; /* length of token */ u8 version; /* TOKEN_VERSION_EP11_AES (0x03) */ u8 res1; /* unused */ u16 keybitlen; /* clear key bit len, 0 for unknown */ } head; }; u8 wkvp[16]; /* wrapping key verification pattern */ u64 attr; /* boolean key attributes */ u64 mode; /* mode bits */ u16 version; /* 0x1234, ep11 blob struct version */ u8 iv[14]; u8 encrypted_key_data[144]; u8 mac[32]; u8 padding[64]; } __packed; #define AESDATA_KEY_SIZE sizeof(struct aesdatakeytoken) #define AESCIPHER_KEY_SIZE sizeof(struct aescipherkeytoken) #define EP11_KEY_SIZE sizeof(struct ep11keytoken) /* MAX/MIN from zt_common.h produces warnings for variable length arrays */ #define _MIN(a, b) ((a) < (b) ? (a) : (b)) #define _MAX(a, b) ((a) > (b) ? (a) : (b)) #define MAX_SECURE_KEY_SIZE _MAX(EP11_KEY_SIZE, \ _MAX(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)) #define MIN_SECURE_KEY_SIZE _MIN(EP11_KEY_SIZE, \ _MIN(AESDATA_KEY_SIZE, AESCIPHER_KEY_SIZE)) #define MAXPROTKEYSIZE 64 /* a protected key blob may be up to 64 bytes */ /* Struct to hold protected key and length info */ struct pkey_protkey { u32 type; /* key type, one of the PKEY_KEYTYPE_AES values */ u32 len; /* bytes actually stored in protkey[] */ u8 protkey[MAXPROTKEYSIZE]; /* the protected key blob */ }; struct pkey_seckey { u8 seckey[AESDATA_KEY_SIZE]; /* the secure key blob */ }; struct pkey_clrkey { u8 clrkey[32]; /* 16, 24, or 32 byte clear key value */ }; #define PKEY_IOCTL_MAGIC 'p' #define AUTOSELECT 0xFFFF #define PKEYDEVICE "/dev/pkey" #define PKEY_KEYTYPE_AES_128 1 #define PKEY_KEYTYPE_AES_192 2 #define PKEY_KEYTYPE_AES_256 3 struct pkey_genseck { u16 cardnr; /* in: card to use or FFFF for any */ u16 domain; /* in: domain or FFFF for any */ u32 keytype; /* in: key type to generate */ struct pkey_seckey seckey; /* out: the secure key blob */ }; #define PKEY_GENSECK _IOWR(PKEY_IOCTL_MAGIC, 0x01, struct pkey_genseck) struct pkey_clr2seck { u16 cardnr; /* in: card to use or FFFF for any */ u16 domain; /* in: domain or FFFF for any*/ u32 keytype; /* in: key type to generate */ struct pkey_clrkey clrkey; /* in: the clear key value */ struct pkey_seckey seckey; /* out: the secure key blob */ }; #define PKEY_CLR2SECK _IOWR(PKEY_IOCTL_MAGIC, 0x02, struct pkey_clr2seck) struct pkey_verifykey { struct pkey_seckey seckey; /* in: the secure key blob */ u16 cardnr; /* out: card number */ u16 domain; /* out: domain number */ u16 keysize; /* out: key size in bits */ u32 attributes; /* out: attribute bits */ }; #define PKEY_VERIFY_ATTR_AES 0x0001 /* key is an AES key */ #define PKEY_VERIFY_ATTR_OLD_MKVP 0x0100 /* key has old MKVP value */ #define PKEY_VERIFYKEY _IOWR(PKEY_IOCTL_MAGIC, 0x07, struct pkey_verifykey) enum pkey_key_type { PKEY_TYPE_CCA_DATA = (u32) 1, PKEY_TYPE_CCA_CIPHER = (u32) 2, PKEY_TYPE_EP11 = (u32) 3, }; enum pkey_key_size { PKEY_SIZE_AES_128 = (u32) 128, PKEY_SIZE_AES_192 = (u32) 192, PKEY_SIZE_AES_256 = (u32) 256, PKEY_SIZE_UNKNOWN = (u32) 0xFFFFFFFF, }; #define PKEY_FLAGS_MATCH_CUR_MKVP 0x00000002 #define PKEY_FLAGS_MATCH_ALT_MKVP 0x00000004 #define PKEY_KEYGEN_XPRT_SYM 0x00008000 #define PKEY_KEYGEN_XPRT_UASY 0x00004000 #define PKEY_KEYGEN_XPRT_AASY 0x00002000 #define PKEY_KEYGEN_XPRT_RAW 0x00001000 #define PKEY_KEYGEN_XPRT_CPAC 0x00000800 #define PKEY_KEYGEN_XPRT_DES 0x00000080 #define PKEY_KEYGEN_XPRT_AES 0x00000040 #define PKEY_KEYGEN_XPRT_RSA 0x00000008 struct pkey_apqn { u16 card; u16 domain; }; struct pkey_genseck2 { struct pkey_apqn *apqns; /* in: ptr to list of apqn targets */ u32 apqn_entries; /* in: # of apqn target list entries */ enum pkey_key_type type; /* in: key type to generate */ enum pkey_key_size size; /* in: key size to generate */ u32 keygenflags; /* in: key generation flags */ u8 *key; /* in: pointer to key blob buffer */ u32 keylen; /* in: available key blob buffer size */ /* out: actual key blob size */ }; #define PKEY_GENSECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x11, struct pkey_genseck2) struct pkey_clr2seck2 { struct pkey_apqn *apqns; /* in: ptr to list of apqn targets */ u32 apqn_entries; /* in: # of apqn target list entries */ enum pkey_key_type type; /* in: key type to generate */ enum pkey_key_size size; /* in: key size to generate */ u32 keygenflags; /* in: key generation flags */ struct pkey_clrkey clrkey; /* in: the clear key value */ u8 *key; /* in: pointer to key blob buffer */ u32 keylen; /* in: available key blob buffer size */ /* out: actual key blob size */ }; #define PKEY_CLR2SECK2 _IOWR(PKEY_IOCTL_MAGIC, 0x12, struct pkey_clr2seck2) struct pkey_verifykey2 { u8 *key; /* in: pointer to key blob */ u32 keylen; /* in: key blob size */ u16 cardnr; /* in/out: card number */ u16 domain; /* in/out: domain number */ enum pkey_key_type type; /* out: the key type */ enum pkey_key_size size; /* out: the key size */ u32 flags; /* out: additional key info flags */ }; #define PKEY_VERIFYKEY2 _IOWR(PKEY_IOCTL_MAGIC, 0x17, struct pkey_verifykey2) struct pkey_apqns4key { u8 *key; /* in: pointer to key blob */ u32 keylen; /* in: key blob size */ u32 flags; /* in: match controlling flags */ struct pkey_apqn *apqns; /* in/out: ptr to list of apqn targets*/ u32 apqn_entries; /* in: max # of apqn entries in list */ /* out: # apqns stored into the list */ }; #define PKEY_APQNS4K _IOWR(PKEY_IOCTL_MAGIC, 0x1B, struct pkey_apqns4key) struct pkey_apqns4keytype { enum pkey_key_type type; /* in: key type */ u8 cur_mkvp[32]; /* in: current mkvp */ u8 alt_mkvp[32]; /* in: alternate mkvp */ u32 flags; /* in: match controlling flags */ struct pkey_apqn *apqns; /* in/out: ptr to list of apqn targets*/ u32 apqn_entries; /* in: max # of apqn entries in list */ /* out: # apqns stored into the list */ }; #define PKEY_APQNS4KT _IOWR(PKEY_IOCTL_MAGIC, 0x1C, struct pkey_apqns4keytype) struct pkey_sec2protk { u16 cardnr; /* in: card to use or FFFF for any */ u16 domain; /* in: domain or FFFF for any */ struct pkey_seckey seckey; /* in: the secure key blob */ struct pkey_protkey protkey; /* out: the protected key */ }; #define PKEY_SEC2PROTK _IOWR(PKEY_IOCTL_MAGIC, 0x03, struct pkey_sec2protk) struct pkey_genprotk { u32 keytype; /* in: key type to generate */ struct pkey_protkey protkey; /* out: the protected key */ }; #define PKEY_GENPROTK _IOWR(PKEY_IOCTL_MAGIC, 0x08, struct pkey_genprotk) struct pkey_kblob2pkey2 { u8 *key; /* in: pointer to key blob */ u32 keylen; /* in: key blob size */ struct pkey_apqn *apqns; /* in: ptr to list of apqn targets */ u32 apqn_entries; /* in: # of apqn target list entries */ struct pkey_protkey protkey; /* out: the protected key */ }; #define PKEY_KBLOB2PROTK2 _IOWR(PKEY_IOCTL_MAGIC, 0x1A, struct pkey_kblob2pkey2) #define KEY_TYPE_CCA_AESDATA "CCA-AESDATA" #define KEY_TYPE_CCA_AESCIPHER "CCA-AESCIPHER" #define KEY_TYPE_EP11_AES "EP11-AES" #define DEFAULT_KEYBITS 256 #define PAES_BLOCK_SIZE 16 #define ENC_ZERO_LEN (2 * PAES_BLOCK_SIZE) #define VERIFICATION_PATTERN_LEN (2 * ENC_ZERO_LEN + 1) #define MKVP_LENGTH 16 static const u8 zero_mkvp[MKVP_LENGTH] = { 0x00 }; #define MKVP_EQ(mkvp1, mkvp2) (memcmp(mkvp1, mkvp2, MKVP_LENGTH) == 0) #define MKVP_ZERO(mkvp) (mkvp == NULL || MKVP_EQ(mkvp, zero_mkvp)) enum card_type { CARD_TYPE_ANY = -1, CARD_TYPE_CCA = 1, CARD_TYPE_EP11 = 2, }; struct ext_lib { struct cca_lib *cca; struct ep11_lib *ep11; }; bool is_cca_aes_data_key(const u8 *key, size_t key_size); bool is_cca_aes_cipher_key(const u8 *key, size_t key_size); bool is_ep11_aes_key(const u8 *key, size_t key_size); bool is_xts_key(const u8 *key, size_t key_size); #endif libzpc-1.0.0/src/zkey/utils.c000066400000000000000000000061041413160260300160450ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * Copyright IBM Corp. 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include #include #include #include #include #include #include #include #include #include #include #include "lib/util_path.h" #include "lib/util_file.h" #include "lib/util_libc.h" #include "lib/util_base.h" #include "utils.h" #include "debug.h" #define pr_verbose(verbose, fmt...) do { \ if (verbose) \ DEBUG(fmt); \ } while (0) /** * Checks if the specified card is of the specified type and is online * * @param[in] card card number * @param[in] cardtype card type (CCA, EP11 or ANY) * * @returns 1 if its card of the specified type and is online, * 0 if offline, * -1 if its not the specified type. */ int sysfs_is_card_online(unsigned int card, enum card_type cardtype) { long int online; char *dev_path; char type[20]; int rc = 1; dev_path = util_path_sysfs("bus/ap/devices/card%02x", card); if (!util_path_is_dir(dev_path)) { rc = 0; goto out; } if (util_file_read_l(&online, 10, "%s/online", dev_path) != 0) { rc = 0; goto out; } if (online == 0) { rc = 0; goto out; } if (util_file_read_line(type, sizeof(type), "%s/type", dev_path) != 0) { rc = 0; goto out; } if (strncmp(type, "CEX", 3) != 0 || strlen(type) < 5) { rc = 0; goto out; } switch (cardtype) { case CARD_TYPE_CCA: if (type[4] != 'C') { rc = -1; goto out; } break; case CARD_TYPE_EP11: if (type[4] != 'P') { rc = -1; goto out; } break; default: break; } out: free(dev_path); return rc; } /** * Gets the 8-16 character ASCII serial number string of an card from the sysfs. * * @param[in] card card number * @param[out] serialnr Result buffer. Must be at least SERIALNR_LENGTH long. * @param[in] verbose if true, verbose messages are printed * * @returns 0 if the serial number was returned. -ENODEV if the APQN is not * available, or is not a CCA or EP11 card. * -ENOTSUP if the serialnr sysfs attribute is not available, because * the zcrypt kernel module is on an older level. */ int sysfs_get_serialnr(unsigned int card, char *serialnr, bool verbose) { char *dev_path; int rc = 0; if (serialnr == NULL) return -EINVAL; if (sysfs_is_card_online(card, CARD_TYPE_ANY) != 1) return -ENODEV; dev_path = util_path_sysfs("bus/ap/devices/card%02x", card); if (!util_path_is_dir(dev_path)) { rc = -ENODEV; goto out; } if (util_file_read_line(serialnr, SERIALNR_LENGTH, "%s/serialnr", dev_path) != 0) { rc = -ENOTSUP; goto out; } if (strlen(serialnr) == 0) { rc = -ENODEV; goto out; } pr_verbose(verbose, "Serial number of %02x: %s", card, serialnr); out: if (rc != 0) pr_verbose(verbose, "Failed to get serial number for " "%02x: %s", card, strerror(-rc)); free(dev_path); return rc; } libzpc-1.0.0/src/zkey/utils.h000066400000000000000000000010701413160260300160470ustar00rootroot00000000000000/* * zkey - Generate, re-encipher, and validate secure keys * * This header file defines the interface to the CCA host library. * * Copyright IBM Corp. 2019 * * s390-tools is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef UTILS_H #define UTILS_H #include "lib/zt_common.h" #include "pkey.h" int sysfs_is_card_online(unsigned int card, enum card_type cardtype); #define SERIALNR_LENGTH 17 int sysfs_get_serialnr(unsigned int card, char *serialnr, bool verbose); #endif libzpc-1.0.0/test/000077500000000000000000000000001413160260300137465ustar00rootroot00000000000000libzpc-1.0.0/test/TEST.md000066400000000000000000000002711413160260300150470ustar00rootroot00000000000000test === testlib --- Functions used by multiple test suites. b_*test* --- Simple build tests. t_*testsuite* --- Test suites using the googletest framework. Part of the test program. libzpc-1.0.0/test/b_aes_cbc.c000066400000000000000000000004341413160260300157730ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for aes_cbc.h. */ #include "zpc/aes_cbc.h" #include "zpc/aes_cbc.h" int b_aes_cbc_not_empty; libzpc-1.0.0/test/b_aes_ccm.c000066400000000000000000000004341413160260300160060ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for aes_ccm.h. */ #include "zpc/aes_ccm.h" #include "zpc/aes_ccm.h" int b_aes_ccm_not_empty; libzpc-1.0.0/test/b_aes_cmac.c000066400000000000000000000004401413160260300161440ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for aes_cmac.h. */ #include "zpc/aes_cmac.h" #include "zpc/aes_cmac.h" int b_aes_cmac_not_empty; libzpc-1.0.0/test/b_aes_ecb.c000066400000000000000000000004341413160260300157750ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for aes_ecb.h. */ #include "zpc/aes_ecb.h" #include "zpc/aes_ecb.h" int b_aes_ecb_not_empty; libzpc-1.0.0/test/b_aes_gcm.c000066400000000000000000000004341413160260300160120ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for aes_gcm.h. */ #include "zpc/aes_gcm.h" #include "zpc/aes_gcm.h" int b_aes_gcm_not_empty; libzpc-1.0.0/test/b_aes_key.c000066400000000000000000000004341413160260300160340ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for aes_key.h. */ #include "zpc/aes_key.h" #include "zpc/aes_key.h" int b_aes_key_not_empty; libzpc-1.0.0/test/b_aes_xts.c000066400000000000000000000004341413160260300160620ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for aes_xts.h. */ #include "zpc/aes_xts.h" #include "zpc/aes_xts.h" int b_aes_xts_not_empty; libzpc-1.0.0/test/b_error.c000066400000000000000000000004241413160260300155440ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for error.h. */ #include "zpc/error.h" #include "zpc/error.h" int b_error_not_empty; libzpc-1.0.0/test/b_headers.c000066400000000000000000000016721413160260300160340ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ /* * Build test for public header files. */ #include "zpc/error.h" #include "zpc/aes_key.h" #include "zpc/aes_gcm.h" #include "zpc/aes_ccm.h" #include "zpc/aes_xts.h" #include "zpc/aes_cbc.h" #include "zpc/aes_ecb.h" #include "zpc/aes_cmac.h" #ifndef ZPC_ERROR_H # error "ZPC_ERROR_H undefined." #endif #ifndef ZPC_AES_KEY_H # error "ZPC_AES_KEY_H undefined." #endif #ifndef ZPC_AES_GCM_H # error "ZPC_AES_GCM_H undefined." #endif #ifndef ZPC_AES_CCM_H # error "ZPC_AES_CCM_H undefined." #endif #ifndef ZPC_AES_XTS_H # error "ZPC_AES_XTS_H undefined." #endif #ifndef ZPC_AES_CBC_H # error "ZPC_AES_CBC_H undefined." #endif #ifndef ZPC_AES_ECB_H # error "ZPC_AES_ECB_H undefined." #endif #ifndef ZPC_AES_CMAC_H # error "ZPC_AES_CMC_H undefined." #endif int b_headers_not_empty; libzpc-1.0.0/test/b_platform.c000066400000000000000000000004511413160260300162370ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #if !defined(__linux__) && !defined(__s390x__) # error "Supported platforms: linux-s390x." #endif int b_platform_not_empty; libzpc-1.0.0/test/t_aes_cbc.cc000066400000000000000000001041741413160260300161660ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "gtest/gtest.h" #include "zpc/aes_cbc.h" #include "zpc/error.h" #include "aes_key_local.h" /* de-opaquify struct zpc_aes_key */ #include "aes_cbc_local.h" /* de-opaquify struct zpc_aes_cbc */ #include #include #include #include static void __run_json(const char *json); TEST(aes_cbc, alloc) { struct zpc_aes_cbc *aes_cbc; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_cbc_alloc(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); aes_cbc = NULL; rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); aes_cbc = (struct zpc_aes_cbc *)&aes_cbc; rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); } TEST(aes_cbc, free) { struct zpc_aes_cbc *aes_cbc; int rc; TESTLIB_ENV_AES_KEY_CHECK(); zpc_aes_cbc_free(NULL); aes_cbc = NULL; zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); } TEST(aes_cbc, set_key) { struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; u8 clearkey[32], iv[16]; unsigned int flags = 0; const char *mkvp, *apqns[257]; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, clearkey); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_cbc_set_key(NULL, aes_key); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_cbc_set_key(aes_cbc, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cbc, set_iv) { struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; const char *mkvp, *apqns[257]; u8 iv[16]; int rc, size, type; unsigned int flags; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_cbc_set_iv(NULL, iv); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_cbc_set_iv(aes_cbc, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cbc, encrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; const char *mkvp, *apqns[257]; u8 iv[16], m[64], c[64]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, c, m, 64); EXPECT_EQ(rc, 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cbc, decrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; const char *mkvp, *apqns[257]; u8 iv[16], m[64], c[64]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, m, c, 64); EXPECT_EQ(rc, 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cbc, pc) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_cbc *aes_cbc1, *aes_cbc2; const char *mkvp, *apqns[257]; u8 iv[16], m[96], c[96], key[32], m_bak[96]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); memcpy(m_bak, m, 96); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc1, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc2, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc2, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_cbc_encrypt(aes_cbc2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_cbc_encrypt(aes_cbc2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_cbc_encrypt(aes_cbc1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); /* Random protected key */ rc = zpc_aes_cbc_set_key(aes_cbc1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc1, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc2, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_cbc_encrypt(aes_cbc2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_cbc_encrypt(aes_cbc2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_cbc_encrypt(aes_cbc1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); zpc_aes_cbc_free(&aes_cbc2); zpc_aes_cbc_free(&aes_cbc1); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_cbc, stream_inplace_kat1) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen, ivlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; unsigned int flags; int type, rc; const char *keystr = "b6f9afbfe5a1562bba1368fc72ac9d9c"; const char *ivstr = "3f9d5ebe250ee7ce384b0d00ee849322"; const char *msgstr = "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1"; const char *ctstr = "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(msg); free(ct); } TEST(aes_cbc, stream_inplace_kat2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; unsigned int flags; int type, rc; const char *keystr = "b6f9afbfe5a1562bba1368fc72ac9d9c"; const char *ivstr = "3f9d5ebe250ee7ce384b0d00ee849322"; const char *msgstr = "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1"; const char *ctstr = "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, msglen); /* Works iff msglen == 0 mod 16 */ EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, msglen); /* Works iff msglen == 0 mod 16 */ EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(msg); free(ct); } TEST(aes_cbc, nist_kat) { TESTLIB_ENV_AES_KEY_CHECK(); __run_json("nist_aes_cbc.json"); } static void __run_json(const char *json) { const char *tv = json, *str; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; unsigned int flags; u8 *key = NULL, *iv = NULL; u8 *pt = NULL, *pt_out = NULL, *ct = NULL, *ct_out = NULL; int rc, keysize = 0; size_t ptlen, ctlen, i, j, max; json_object *jkey, *jiv, *jmsg, *jct, *jtmp, *jtestgroups, *jfile, *jkeysize, *jtests; json_bool b; int type; type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); jfile = json_object_from_file(tv); ASSERT_NE(jfile, nullptr); b = json_object_object_get_ex(jfile, "testGroups", &jtestgroups); ASSERT_TRUE(b); for (i = 0; i < (size_t)json_object_array_length(jtestgroups); i++) { jtmp = json_object_array_get_idx(jtestgroups, i); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "keySize", &jkeysize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tests", &jtests); ASSERT_TRUE(b); keysize = json_object_get_int(jkeysize); rc = zpc_aes_key_set_size(aes_key, keysize); EXPECT_EQ(rc, 0); for (j = 0; j < (size_t)json_object_array_length(jtests); j++) { jtmp = json_object_array_get_idx(jtests, j); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "key", &jkey); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "iv", &jiv); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "msg", &jmsg); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "ct", &jct); ASSERT_TRUE(b); str = json_object_get_string(jkey); ASSERT_NE(str, nullptr); key = testlib_hexstr2buf(str, NULL); ASSERT_NE(key, nullptr); str = json_object_get_string(jiv); ASSERT_NE(str, nullptr); iv = testlib_hexstr2buf(str, NULL); str = json_object_get_string(jmsg); ASSERT_NE(str, nullptr); pt = testlib_hexstr2buf(str, &ptlen); str = json_object_get_string(jct); ASSERT_NE(str, nullptr); ct = testlib_hexstr2buf(str, &ctlen); max = ptlen > ctlen ? ptlen : ctlen; pt_out = NULL; ct_out = NULL; if (max > 0) { pt_out = (unsigned char *)calloc(1, max); ASSERT_NE(pt_out, nullptr); ct_out = (unsigned char *)calloc(1, max); ASSERT_NE(ct_out, nullptr); } rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, ct_out, pt, ptlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(ct_out, ct, ctlen) == 0); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, pt_out, ct, ctlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(pt_out, pt, ptlen) == 0); /* Unset key. */ rc = zpc_aes_cbc_set_key(aes_cbc, NULL); EXPECT_EQ(rc, 0); free(key); key = NULL; free(iv); iv = NULL; free(pt); pt = NULL; free(pt_out); pt_out = NULL; free(ct); ct = NULL; free(ct_out); ct_out = NULL; } } zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cbc, rederive_protected_key1) { struct zpc_aes_key *aes_key1; struct zpc_aes_cbc *aes_cbc1, *aes_cbc2, *aes_cbc3; u8 iv[16], m[96], c[96]; int rc, size; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc2); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc3); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc3, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); /* Random protected keys cannot rbe re-derived. */ rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc1, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc2, iv); EXPECT_EQ(rc, 0); memset(aes_cbc2->param.protkey, 0, sizeof(aes_cbc2->param.protkey)); rc = zpc_aes_cbc_encrypt(aes_cbc2, c, m, 96); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_cbc_set_key(aes_cbc3, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_iv(aes_cbc3, iv); EXPECT_EQ(rc, 0); memset(aes_cbc3->param.protkey, 0, sizeof(aes_cbc3->param.protkey)); rc = zpc_aes_cbc_decrypt(aes_cbc3, m, c, 96); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); zpc_aes_cbc_free(&aes_cbc3); zpc_aes_cbc_free(&aes_cbc2); zpc_aes_cbc_free(&aes_cbc1); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_cbc3, nullptr); EXPECT_EQ(aes_cbc2, nullptr); EXPECT_EQ(aes_cbc1, nullptr); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_cbc, rederive_protected_key2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen, ivlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; unsigned int flags; int type, rc; const char *keystr = "b6f9afbfe5a1562bba1368fc72ac9d9c"; const char *ivstr = "3f9d5ebe250ee7ce384b0d00ee849322"; const char *msgstr = "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1"; const char *ctstr = "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_encrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(msg); free(ct); } TEST(aes_cbc, reencipher) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen, ivlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cbc *aes_cbc; unsigned int flags; int type, rc; const char *keystr = "b6f9afbfe5a1562bba1368fc72ac9d9c"; const char *ivstr = "3f9d5ebe250ee7ce384b0d00ee849322"; const char *msgstr = "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1"; const char *ctstr = "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_encrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(msg); free(ct); } static void __task(struct zpc_aes_key *aes_key) { struct zpc_aes_cbc *aes_cbc; unsigned char buf[4096]; size_t ivlen, msglen, ctlen; int rc, i; const char *ivstr = "3f9d5ebe250ee7ce384b0d00ee849322"; const char *msgstr = "db397ec22718dbffb9c9d13de0efcd4611bf792be4fce0dc5f25d4f577ed8cdbd4eb9208d593dda3d4653954ab64f05676caa3ce9bfa795b08b67ceebc923fdc89a8c431188e9e482d8553982cf304d1"; const char *ctstr = "10ea27b19e16b93af169c4a88e06e35c99d8b420980b058e34b4b8f132b13766f72728202b089f428fecdb41c79f8aa0d0ef68f5786481cca29e2126f69bc14160f1ae2187878ba5c49cf3961e1b7ee9"; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); rc = zpc_aes_cbc_alloc(&aes_cbc); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_set_key(aes_cbc, aes_key); EXPECT_EQ(rc, 0); for (i = 0; i < 1000; i++) { /* Encrypt */ memcpy(buf, msg, msglen); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_encrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_encrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_cbc_set_iv(aes_cbc, iv); EXPECT_EQ(rc, 0); memset(aes_cbc->param.protkey, 0, sizeof(aes_cbc->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cbc_decrypt(aes_cbc, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cbc_decrypt(aes_cbc, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); } zpc_aes_cbc_free(&aes_cbc); EXPECT_EQ(aes_cbc, nullptr); free(iv); free(msg); free(ct); } TEST(aes_cbc, threads) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; unsigned int flags; int type, rc, i; std::thread *t[500]; const char *keystr = "b6f9afbfe5a1562bba1368fc72ac9d9c"; u8 *key = testlib_hexstr2buf(keystr, &keylen); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); for (i = 0; i < 500; i++) { t[i] = new std::thread(__task, aes_key); } /* Do something with key object while threads are working with it. */ rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ for (i = 0; i < 500; i++) { memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ usleep(1); } for (i = 0; i < 500; i++) { t[i]->join(); delete t[i]; } zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); } libzpc-1.0.0/test/t_aes_ccm.cc000066400000000000000000001153641413160260300162040ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "gtest/gtest.h" #include "zpc/aes_ccm.h" #include "zpc/error.h" #include "aes_key_local.h" /* de-opaquify struct zpc_aes_key */ #include "aes_ccm_local.h" /* de-opaquify struct zpc_aes_ccm */ #include #include #include #include static void __run_json(const char *json); TEST(aes_ccm, alloc) { struct zpc_aes_ccm *aes_ccm; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_ccm_alloc(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); aes_ccm = NULL; rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); aes_ccm = (struct zpc_aes_ccm *)&aes_ccm; rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); } TEST(aes_ccm, free) { struct zpc_aes_ccm *aes_ccm; int rc; TESTLIB_ENV_AES_KEY_CHECK(); zpc_aes_ccm_free(NULL); aes_ccm = NULL; zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); } TEST(aes_ccm, set_key) { struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; u8 clearkey[32], iv[12]; unsigned int flags = 0; const char *mkvp, *apqns[257]; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, clearkey); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_ccm_set_key(NULL, aes_key); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_ccm_set_key(aes_ccm, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 12); EXPECT_EQ(rc, 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ccm, set_iv) { struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; const char *mkvp, *apqns[257]; u8 iv[16]; int rc, size, type; unsigned int flags; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(NULL, NULL, 0); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_ccm_set_iv(NULL, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_ccm_set_iv(aes_ccm, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 0); EXPECT_EQ(rc, ZPC_ERROR_IVSIZE); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, SIZE_MAX); EXPECT_EQ(rc, ZPC_ERROR_IVSIZE); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 13); EXPECT_EQ(rc, 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ccm, encrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; const char *mkvp, *apqns[257]; u8 iv[12], aad[99], m[99], tag[12], c[99]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_encrypt(aes_ccm, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ccm, decrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; const char *mkvp, *apqns[257]; u8 iv[12], aad[99], m[99], tag[12], c[99]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ccm, pc) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_ccm *aes_ccm1, *aes_ccm2; const char *mkvp, *apqns[257]; u8 iv[12], aad[99], m[99], tag[12], c[99], key[32], m_bak[99]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); memcpy(m_bak, m, 99); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm1, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm2, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm2, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_encrypt(aes_ccm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_ccm_encrypt(aes_ccm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_ccm_encrypt(aes_ccm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); c[0] ^= 1; rc = zpc_aes_ccm_decrypt(aes_ccm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); rc = zpc_aes_ccm_encrypt(aes_ccm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_ccm_decrypt(aes_ccm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); memcpy(m_bak, m, 99); /* Random protected key */ rc = zpc_aes_ccm_set_key(aes_ccm1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm1, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm2, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_encrypt(aes_ccm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_ccm_encrypt(aes_ccm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_ccm_encrypt(aes_ccm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); c[0] ^= 1; rc = zpc_aes_ccm_decrypt(aes_ccm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); rc = zpc_aes_ccm_encrypt(aes_ccm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_ccm_decrypt(aes_ccm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); zpc_aes_ccm_free(&aes_ccm2); zpc_aes_ccm_free(&aes_ccm1); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_ccm, stream_inplace_kat1) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; unsigned int flags; int type, rc; const char *keystr = "e258b117c2fdd75587f07b400ae4af3e673a51dcf761e4ca"; const char *ivstr = "5ead03aa8c720d21b77075db"; const char *aadstr = "27702950960b9c79"; const char *msgstr = "afe96113a684bc52a6d962cf2724f6791d"; const char *ctstr = "7830446f333057d996a1a79b21c68d8b43"; const char *tagstr = "72ac478a66f5637563f1f12c1d0267ca"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_ccm, stream_inplace_kat2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; unsigned int flags; int type, rc; const char *keystr = "e258b117c2fdd75587f07b400ae4af3e673a51dcf761e4ca"; const char *ivstr = "5ead03aa8c720d21b77075db"; const char *aadstr = "27702950960b9c79"; const char *msgstr = "afe96113a684bc52a6d962cf2724f6791d"; const char *ctstr = "7830446f333057d996a1a79b21c68d8b43"; const char *tagstr = "72ac478a66f5637563f1f12c1d0267ca"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, msglen); /* Works iff msglen == 0 mod 16 */ EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_ccm, wycheproof_kat) { TESTLIB_ENV_AES_KEY_CHECK(); __run_json("wycheproof/src/wycheproof/testvectors/aes_ccm_test.json"); } static void __run_json(const char *json) { const char *tv = json, *str; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; unsigned int flags; u8 *key = NULL, *iv = NULL, *aad = NULL; u8 *pt = NULL, *pt_out = NULL, *ct = NULL, *ct_out = NULL; u8 *tag = NULL, *tag_out = NULL; int rc, tagsize = 0, ivsize = 0, keysize = 0; int valid = 0, ivlen0 = 0, tag0 = 0, nonce0 = 0; size_t aadlen, ptlen, ctlen, taglen, i, j, k, max; json_object *jkey, *jiv, *jtag, *jaad, *jmsg, *jct, *jresult, *jflags, *jtmp, *jtestgroups, *jfile, *jkeysize, *jivsize, *jtagsize, *jtests; json_bool b; int type; type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); jfile = json_object_from_file(tv); ASSERT_NE(jfile, nullptr); b = json_object_object_get_ex(jfile, "testGroups", &jtestgroups); ASSERT_TRUE(b); for (i = 0; i < (size_t)json_object_array_length(jtestgroups); i++) { jtmp = json_object_array_get_idx(jtestgroups, i); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "keySize", &jkeysize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "ivSize", &jivsize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tagSize", &jtagsize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tests", &jtests); ASSERT_TRUE(b); keysize = json_object_get_int(jkeysize); ivsize = json_object_get_int(jivsize); tagsize = json_object_get_int(jtagsize); rc = zpc_aes_key_set_size(aes_key, keysize); EXPECT_EQ(rc, 0); for (j = 0; j < (size_t)json_object_array_length(jtests); j++) { jtmp = json_object_array_get_idx(jtests, j); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "key", &jkey); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "iv", &jiv); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tag", &jtag); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "aad", &jaad); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "msg", &jmsg); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "ct", &jct); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "flags", &jflags); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "result", &jresult); ASSERT_TRUE(b); str = json_object_get_string(jkey); ASSERT_NE(str, nullptr); key = testlib_hexstr2buf(str, NULL); ASSERT_NE(key, nullptr); str = json_object_get_string(jiv); ASSERT_NE(str, nullptr); iv = testlib_hexstr2buf(str, NULL); str = json_object_get_string(jtag); ASSERT_NE(str, nullptr); tag = testlib_hexstr2buf(str, &taglen); ASSERT_NE(tag, nullptr); tag_out = (unsigned char *)calloc(1, taglen); ASSERT_NE(tag_out, nullptr); str = json_object_get_string(jaad); ASSERT_NE(str, nullptr); aad = testlib_hexstr2buf(str, &aadlen); str = json_object_get_string(jmsg); ASSERT_NE(str, nullptr); pt = testlib_hexstr2buf(str, &ptlen); str = json_object_get_string(jct); ASSERT_NE(str, nullptr); ct = testlib_hexstr2buf(str, &ctlen); str = json_object_get_string(jresult); ASSERT_NE(str, nullptr); if (strcmp(str, "valid") == 0 || strcmp(str, "acceptable") == 0) valid = 1; else valid = 0; for (k = 0; k < (size_t)json_object_array_length(jflags); k++) { jtmp = json_object_array_get_idx(jflags, k); ASSERT_NE(jtmp, nullptr); str = json_object_get_string(jtmp); if (strcmp(str, "LongIv") == 0) ivlen0 = 1; else ivlen0 = 0; str = json_object_get_string(jtmp); if (strcmp(str, "InvalidNonceSize") == 0) nonce0 = 1; else nonce0 = 0; str = json_object_get_string(jtmp); if (strcmp(str, "InvalidTagSize") == 0) tag0 = 1; else tag0 = 0; } max = ptlen > ctlen ? ptlen : ctlen; pt_out = NULL; ct_out = NULL; if (max > 0) { pt_out = (unsigned char *)calloc(1, max); ASSERT_NE(pt_out, nullptr); ct_out = (unsigned char *)calloc(1, max); ASSERT_NE(ct_out, nullptr); } rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm, (ivlen0 || nonce0) ? (unsigned char *)1 : iv, ivsize / 8); EXPECT_EQ(rc, (ivlen0 || nonce0) ? ZPC_ERROR_IVSIZE : 0); if (!ivlen0 && !nonce0) { rc = zpc_aes_ccm_encrypt(aes_ccm, ct_out, tag_out, tagsize / 8, aad, aadlen, pt, ptlen); EXPECT_EQ(rc, tag0 ? ZPC_ERROR_TAGSIZE : 0); if (rc == 0) { EXPECT_TRUE(memcmp(ct_out, ct, ctlen) == 0); if (valid) { EXPECT_TRUE(memcmp(tag_out, tag, tagsize / 8) == 0); } } rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivsize / 8); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_decrypt(aes_ccm, pt_out, tag, tagsize / 8, aad, aadlen, ct, ctlen); EXPECT_EQ(rc, tag0 ? ZPC_ERROR_TAGSIZE : (valid ? 0 : ZPC_ERROR_TAGMISMATCH)); if (rc == 0) { EXPECT_TRUE(memcmp(pt_out, pt, ptlen) == 0); } } /* Unset key. */ rc = zpc_aes_ccm_set_key(aes_ccm, NULL); EXPECT_EQ(rc, 0); free(key); key = NULL; free(iv); iv = NULL; free(aad); aad = NULL; free(pt); pt = NULL; free(pt_out); pt_out = NULL; free(ct); ct = NULL; free(ct_out); ct_out = NULL; free(tag); tag = NULL; free(tag_out); tag_out = NULL; } } zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ccm, rederive_protected_key1) { struct zpc_aes_key *aes_key1; struct zpc_aes_ccm *aes_ccm1, *aes_ccm2, *aes_ccm3; u8 iv[12], aad[99], m[99], tag[16], c[99]; /* use ivlen != 12 bytes such that it must be processed by kma */ int rc, size; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm2); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm3); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm3, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); /* Random protected keys cannot be re-derived. */ rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm1, iv, sizeof(iv)); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm2, iv, sizeof(iv)); EXPECT_EQ(rc, 0); memset(aes_ccm2->param_kma.protkey, 0, sizeof(aes_ccm2->param_kma.protkey)); memset(aes_ccm2->param_kmac.protkey, 0, sizeof(aes_ccm2->param_kmac.protkey)); rc = zpc_aes_ccm_encrypt(aes_ccm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_ccm_set_key(aes_ccm3, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_iv(aes_ccm3, iv, sizeof(iv)); EXPECT_EQ(rc, 0); memset(aes_ccm3->param_kma.protkey, 0, sizeof(aes_ccm3->param_kma.protkey)); memset(aes_ccm2->param_kma.protkey, 0, sizeof(aes_ccm2->param_kmac.protkey)); rc = zpc_aes_ccm_decrypt(aes_ccm3, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_ccm_set_key(aes_ccm1, aes_key1); EXPECT_EQ(rc, 0); zpc_aes_ccm_free(&aes_ccm3); zpc_aes_ccm_free(&aes_ccm2); zpc_aes_ccm_free(&aes_ccm1); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_ccm3, nullptr); EXPECT_EQ(aes_ccm2, nullptr); EXPECT_EQ(aes_ccm1, nullptr); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_ccm, rederive_protected_key2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; unsigned int flags; int type, rc; const char *keystr = "e258b117c2fdd75587f07b400ae4af3e673a51dcf761e4ca"; const char *ivstr = "5ead03aa8c720d21b77075db"; const char *aadstr = "27702950960b9c79"; const char *msgstr = "afe96113a684bc52a6d962cf2724f6791d"; const char *ctstr = "7830446f333057d996a1a79b21c68d8b43"; const char *tagstr = "72ac478a66f5637563f1f12c1d0267ca"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, ctlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memcpy(buf, ct, ctlen); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, ctlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_ccm, reencipher) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ccm *aes_ccm; unsigned int flags; int type, rc; const char *keystr = "e258b117c2fdd75587f07b400ae4af3e673a51dcf761e4ca"; const char *ivstr = "5ead03aa8c720d21b77075db"; const char *aadstr = "27702950960b9c79"; const char *msgstr = "afe96113a684bc52a6d962cf2724f6791d"; const char *ctstr = "7830446f333057d996a1a79b21c68d8b43"; const char *tagstr = "72ac478a66f5637563f1f12c1d0267ca"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ccm->param_kma.protkey, 0, sizeof(aes_ccm->param_kma.protkey)); /* force WKaVP mismatch */ memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } static void __task(struct zpc_aes_key *aes_key) { struct zpc_aes_ccm *aes_ccm; unsigned char buf[4096], mac[16]; size_t ivlen, msglen, ctlen, taglen, aadlen; int rc, i; const char *ivstr = "5ead03aa8c720d21b77075db"; const char *aadstr = "27702950960b9c79"; const char *msgstr = "afe96113a684bc52a6d962cf2724f6791d"; const char *ctstr = "7830446f333057d996a1a79b21c68d8b43"; const char *tagstr = "72ac478a66f5637563f1f12c1d0267ca"; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); rc = zpc_aes_ccm_alloc(&aes_ccm); EXPECT_EQ(rc, 0); rc = zpc_aes_ccm_set_key(aes_ccm, aes_key); EXPECT_EQ(rc, 0); for (i = 0; i < 1000; i++) { /* Encrypt */ memcpy(buf, msg, msglen); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_encrypt(aes_ccm, buf, mac, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_ccm_set_iv(aes_ccm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_ccm->param_kmac.protkey, 0, sizeof(aes_ccm->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ccm_decrypt(aes_ccm, buf, tag, taglen, aad, aadlen, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); } zpc_aes_ccm_free(&aes_ccm); EXPECT_EQ(aes_ccm, nullptr); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_ccm, threads) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; unsigned int flags; int type, rc, i; std::thread *t[500]; const char *keystr = "e258b117c2fdd75587f07b400ae4af3e673a51dcf761e4ca"; u8 *key = testlib_hexstr2buf(keystr, &keylen); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); for (i = 0; i < 500; i++) { t[i] = new std::thread(__task, aes_key); } /* Do something with key object while threads are working with it. */ rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ for (i = 0; i < 500; i++) { memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ usleep(1); } for (i = 0; i < 500; i++) { t[i]->join(); delete t[i]; } zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); } libzpc-1.0.0/test/t_aes_cmac.cc000066400000000000000000000723301413160260300163400ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "gtest/gtest.h" #include "zpc/aes_cmac.h" #include "zpc/error.h" #include "aes_key_local.h" /* de-opaquify struct zpc_aes_key */ #include "aes_cmac_local.h" /* de-opaquify struct zpc_aes_cmac */ #include #include #include #include static void __run_json(const char *json); TEST(aes_cmac, alloc) { struct zpc_aes_cmac *aes_cmac; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_cmac_alloc(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); aes_cmac = NULL; rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); aes_cmac = (struct zpc_aes_cmac *)&aes_cmac; rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); } TEST(aes_cmac, free) { struct zpc_aes_cmac *aes_cmac; int rc; TESTLIB_ENV_AES_KEY_CHECK(); zpc_aes_cmac_free(NULL); aes_cmac = NULL; zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); } TEST(aes_cmac, set_key) { struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; u8 clearkey[32]; unsigned int flags = 0; const char *mkvp, *apqns[257]; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, clearkey); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_cmac_set_key(NULL, aes_key); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_cmac_set_key(aes_cmac, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cmac, sign) { struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; const char *mkvp, *apqns[257]; u8 m[99], tag[16]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, tag, 16, m, 99); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cmac, verifyzpc_aes_cmac_verify) { struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; const char *mkvp, *apqns[257]; u8 m[99], tag[16]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, tag, 16, m, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cmac, pc) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_cmac *aes_cmac1, *aes_cmac2; const char *mkvp, *apqns[257]; u8 m[99], tag[16], key[32]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac2, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_cmac_verify(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); rc = zpc_aes_cmac_sign(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_cmac_verify(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); /* Random protected key */ rc = zpc_aes_cmac_set_key(aes_cmac1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_cmac_verify(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); rc = zpc_aes_cmac_sign(aes_cmac1, tag, 16, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_cmac_verify(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); zpc_aes_cmac_free(&aes_cmac2); zpc_aes_cmac_free(&aes_cmac1); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_cmac, stream_inplace_kat1) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, taglen; unsigned char mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; unsigned int flags; int type, rc; const char *keystr = "648a44468d67bb6744b235ee7a3fcd6ed4bdc29ec5b5fa1a"; const char *msgstr = "c59d0d6981cca1be1d5519fc7881e6d230f39f6c12a9e827"; const char *tagstr = "a1b96272ae7f9aef567271795f21d1d3"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Sign */ rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Verify */ rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, tag, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, tag, taglen, msg, msglen); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(msg); free(tag); } TEST(aes_cmac, stream_inplace_kat2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, taglen; unsigned char mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; unsigned int flags; int type, rc; const char *keystr = "648a44468d67bb6744b235ee7a3fcd6ed4bdc29ec5b5fa1a"; const char *msgstr = "c59d0d6981cca1be1d5519fc7881e6d230f39f6c12a9e827"; const char *tagstr = "a1b96272ae7f9aef567271795f21d1d3"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Sign */ rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Verify */ rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, tag, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(msg); free(tag); } TEST(aes_cmac, wycheproof_kat) { TESTLIB_ENV_AES_KEY_CHECK(); __run_json("wycheproof/src/wycheproof/testvectors/aes_cmac_test.json"); } static void __run_json(const char *json) { const char *tv = json, *str; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; unsigned int flags; u8 *key = NULL; u8 *pt = NULL; u8 *tag = NULL, *tag_out = NULL; int rc, tagsize = 0, keysize = 0; int valid = 0; size_t ptlen, taglen, i, j; json_object *jkey, *jtag, *jmsg, *jresult, *jtmp, *jtestgroups, *jfile, *jkeysize, *jtagsize, *jtests; json_bool b; int type; type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); jfile = json_object_from_file(tv); ASSERT_NE(jfile, nullptr); b = json_object_object_get_ex(jfile, "testGroups", &jtestgroups); ASSERT_TRUE(b); for (i = 0; i < (size_t)json_object_array_length(jtestgroups); i++) { jtmp = json_object_array_get_idx(jtestgroups, i); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "keySize", &jkeysize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tagSize", &jtagsize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tests", &jtests); ASSERT_TRUE(b); keysize = json_object_get_int(jkeysize); tagsize = json_object_get_int(jtagsize); rc = zpc_aes_key_set_size(aes_key, keysize); if (keysize != 128 && keysize != 192 && keysize != 256) { EXPECT_EQ(rc, ZPC_ERROR_KEYSIZE); continue; } else { EXPECT_EQ(rc, 0); } for (j = 0; j < (size_t)json_object_array_length(jtests); j++) { jtmp = json_object_array_get_idx(jtests, j); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "key", &jkey); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tag", &jtag); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "msg", &jmsg); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "result", &jresult); ASSERT_TRUE(b); str = json_object_get_string(jkey); ASSERT_NE(str, nullptr); key = testlib_hexstr2buf(str, NULL); ASSERT_NE(key, nullptr); str = json_object_get_string(jtag); ASSERT_NE(str, nullptr); tag = testlib_hexstr2buf(str, &taglen); ASSERT_NE(tag, nullptr); tag_out = (unsigned char *)calloc(1, taglen); ASSERT_NE(tag_out, nullptr); str = json_object_get_string(jmsg); ASSERT_NE(str, nullptr); pt = testlib_hexstr2buf(str, &ptlen); str = json_object_get_string(jresult); ASSERT_NE(str, nullptr); if (strcmp(str, "valid") == 0) valid = 1; else if (strcmp(str, "invalid") == 0) valid = 0; else assert(strcmp(str, "invalid") == 0 || strcmp(str, "valid") == 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, tag_out, tagsize / 8, pt, ptlen); EXPECT_EQ(rc, 0); if (valid) { EXPECT_TRUE(memcmp(tag_out, tag, tagsize / 8) == 0); } rc = zpc_aes_cmac_verify(aes_cmac, tag, tagsize / 8, pt, ptlen); EXPECT_EQ(rc, valid ? 0 : ZPC_ERROR_TAGMISMATCH); /* Unset key. */ rc = zpc_aes_cmac_set_key(aes_cmac, NULL); EXPECT_EQ(rc, 0); free(key); key = NULL; free(pt); pt = NULL; free(tag); tag = NULL; free(tag_out); tag_out = NULL; } } zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_cmac, rederive_protected_key1) { struct zpc_aes_key *aes_key1; struct zpc_aes_cmac *aes_cmac1, *aes_cmac2, *aes_cmac3; u8 m[99], tag[16]; int rc, size; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac2); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac3); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac3, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); /* Random protected keys cannot be re-derived. */ rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac2, aes_key1); EXPECT_EQ(rc, 0); memset(aes_cmac2->param_kmac.protkey, 0, sizeof(aes_cmac2->param_kmac.protkey)); memset(aes_cmac2->param_pcc.protkey, 0, sizeof(aes_cmac2->param_pcc.protkey)); rc = zpc_aes_cmac_sign(aes_cmac2, tag, 16, m, 99); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_cmac_set_key(aes_cmac3, aes_key1); EXPECT_EQ(rc, 0); memset(aes_cmac3->param_kmac.protkey, 0, sizeof(aes_cmac3->param_kmac.protkey)); memset(aes_cmac2->param_pcc.protkey, 0, sizeof(aes_cmac2->param_pcc.protkey)); rc = zpc_aes_cmac_verify(aes_cmac3, tag, 16, m, 99); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_cmac_set_key(aes_cmac1, aes_key1); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac3); zpc_aes_cmac_free(&aes_cmac2); zpc_aes_cmac_free(&aes_cmac1); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_cmac3, nullptr); EXPECT_EQ(aes_cmac2, nullptr); EXPECT_EQ(aes_cmac1, nullptr); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_cmac, rederive_protected_key2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, taglen; unsigned char mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; unsigned int flags; int type, rc; const char *keystr = "648a44468d67bb6744b235ee7a3fcd6ed4bdc29ec5b5fa1a"; const char *msgstr = "c59d0d6981cca1be1d5519fc7881e6d230f39f6c12a9e827"; const char *tagstr = "a1b96272ae7f9aef567271795f21d1d3"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Sign */ rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Sign*/ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Verify */ rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_verify(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); /* Verify */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(msg); free(tag); } TEST(aes_cmac, reencipher) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, taglen; unsigned char mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_cmac *aes_cmac; unsigned int flags; int type, rc; const char *keystr = "648a44468d67bb6744b235ee7a3fcd6ed4bdc29ec5b5fa1a"; const char *msgstr = "c59d0d6981cca1be1d5519fc7881e6d230f39f6c12a9e827"; const char *tagstr = "a1b96272ae7f9aef567271795f21d1d3"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ /* Encrypt */ rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Encrypt */ rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_verify(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); /* Decrypt */ memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(msg); free(tag); } static void __task(struct zpc_aes_key *aes_key) { struct zpc_aes_cmac *aes_cmac; unsigned char mac[16]; size_t msglen, taglen; int rc, i; const char *msgstr = "c59d0d6981cca1be1d5519fc7881e6d230f39f6c12a9e827"; const char *tagstr = "a1b96272ae7f9aef567271795f21d1d3"; u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); rc = zpc_aes_cmac_alloc(&aes_cmac); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_set_key(aes_cmac, aes_key); EXPECT_EQ(rc, 0); for (i = 0; i < 1000; i++) { /* Sign */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_sign(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_sign(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Verify */ memset(aes_cmac->param_kmac.protkey, 0, sizeof(aes_cmac->param_kmac.protkey)); /* force WKaVP mismatch */ memset(aes_cmac->param_pcc.protkey, 0, sizeof(aes_cmac->param_pcc.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_cmac_verify(aes_cmac, NULL, 0, msg, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_cmac_verify(aes_cmac, mac, taglen, msg + 16, msglen - 16); EXPECT_EQ(rc, 0); } zpc_aes_cmac_free(&aes_cmac); EXPECT_EQ(aes_cmac, nullptr); free(msg); free(tag); } TEST(aes_cmac, threads) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; unsigned int flags; int type, rc, i; std::thread *t[500]; const char *keystr = "648a44468d67bb6744b235ee7a3fcd6ed4bdc29ec5b5fa1a"; u8 *key = testlib_hexstr2buf(keystr, &keylen); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); for (i = 0; i < 500; i++) { t[i] = new std::thread(__task, aes_key); } /* Do something with key object while threads are working with it. */ rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ for (i = 0; i < 500; i++) { memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ usleep(1); } for (i = 0; i < 500; i++) { t[i]->join(); delete t[i]; } zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); } libzpc-1.0.0/test/t_aes_ecb.cc000066400000000000000000000625631413160260300161750ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "gtest/gtest.h" #include "zpc/aes_ecb.h" #include "zpc/error.h" #include "aes_key_local.h" /* de-opaquify struct zpc_aes_key */ #include "aes_ecb_local.h" /* de-opaquify struct zpc_aes_ecb */ #include #include #include #include static void __run_json(const char *json); TEST(aes_ecb, alloc) { struct zpc_aes_ecb *aes_ecb; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_ecb_alloc(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); aes_ecb = NULL; rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); aes_ecb = (struct zpc_aes_ecb *)&aes_ecb; rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); } TEST(aes_ecb, free) { struct zpc_aes_ecb *aes_ecb; int rc; TESTLIB_ENV_AES_KEY_CHECK(); zpc_aes_ecb_free(NULL); aes_ecb = NULL; zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); } TEST(aes_ecb, set_key) { struct zpc_aes_key *aes_key; struct zpc_aes_ecb *aes_ecb; u8 clearkey[32]; unsigned int flags = 0; const char *mkvp, *apqns[257]; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, clearkey); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_ecb_set_key(NULL, aes_key); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_ecb_set_key(aes_ecb, NULL); EXPECT_EQ(rc, 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ecb, encrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_ecb *aes_ecb; const char *mkvp, *apqns[257]; u8 m[64], c[64]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_encrypt(aes_ecb, c, m, 64); EXPECT_EQ(rc, 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ecb, decrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_ecb *aes_ecb; const char *mkvp, *apqns[257]; u8 m[64], c[64]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, m, c, 64); EXPECT_EQ(rc, 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ecb, pc) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_ecb *aes_ecb1, *aes_ecb2; const char *mkvp, *apqns[257]; u8 m[80], c[80], key[32], m_bak[80]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); memcpy(m_bak, m, 80); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb2, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_encrypt(aes_ecb1, c, m, 80); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb2, m, c, 80); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 80) == 0); rc = zpc_aes_ecb_encrypt(aes_ecb2, c, m, 80); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb1, m, c, 80); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 80) == 0); /* Random protected key */ rc = zpc_aes_ecb_set_key(aes_ecb1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_encrypt(aes_ecb1, c, m, 80); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb2, m, c, 80); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 80) == 0); rc = zpc_aes_ecb_encrypt(aes_ecb2, c, m, 80); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb1, m, c, 80); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 80) == 0); zpc_aes_ecb_free(&aes_ecb2); zpc_aes_ecb_free(&aes_ecb1); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_ecb, stream_inplace_kat) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ecb *aes_ecb; unsigned int flags; int type, rc; const char *keystr = "605c4139c961b496ca5148f1bdb1bb1901f2101943a0ec10fcdc403d3b0c285a"; const char *msgstr = "68c9885ba2be03181f65f1e04e83d6ba6880467550bcf099be26dc9d9c0af15ab02abac07c116ac862a41da90cfa604f"; const char *ctstr = "a7603d29bbba4c77208bf2f3df9f5ec85204adce012299f2cce7b326ce78f5cf8040343dd291e8cf9f3645726368dc20"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ecb_encrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_encrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ecb_encrypt(aes_ecb, buf, buf, 32); rc = zpc_aes_ecb_encrypt(aes_ecb, buf + 32, buf + 32, msglen - 32); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_ecb_decrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_ecb_decrypt(aes_ecb, buf, buf, 32); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, buf + 32, buf + 32, msglen - 32); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(msg); free(ct); } TEST(aes_ecb, nist_kat) { TESTLIB_ENV_AES_KEY_CHECK(); __run_json("nist_aes_ecb.json"); } static void __run_json(const char *json) { const char *tv = json, *str; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ecb *aes_ecb; unsigned int flags; u8 *key = NULL; u8 *pt = NULL, *pt_out = NULL, *ct = NULL, *ct_out = NULL; int rc, keysize = 0; size_t ptlen, ctlen, i, j, max; json_object *jkey, *jmsg, *jct, *jtmp, *jtestgroups, *jfile, *jkeysize, *jtests; json_bool b; int type; type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); jfile = json_object_from_file(tv); ASSERT_NE(jfile, nullptr); b = json_object_object_get_ex(jfile, "testGroups", &jtestgroups); ASSERT_TRUE(b); for (i = 0; i < (size_t)json_object_array_length(jtestgroups); i++) { jtmp = json_object_array_get_idx(jtestgroups, i); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "keySize", &jkeysize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tests", &jtests); ASSERT_TRUE(b); keysize = json_object_get_int(jkeysize); rc = zpc_aes_key_set_size(aes_key, keysize); EXPECT_EQ(rc, 0); for (j = 0; j < (size_t)json_object_array_length(jtests); j++) { jtmp = json_object_array_get_idx(jtests, j); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "key", &jkey); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "msg", &jmsg); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "ct", &jct); ASSERT_TRUE(b); str = json_object_get_string(jkey); ASSERT_NE(str, nullptr); key = testlib_hexstr2buf(str, NULL); ASSERT_NE(key, nullptr); str = json_object_get_string(jmsg); ASSERT_NE(str, nullptr); pt = testlib_hexstr2buf(str, &ptlen); str = json_object_get_string(jct); ASSERT_NE(str, nullptr); ct = testlib_hexstr2buf(str, &ctlen); max = ptlen > ctlen ? ptlen : ctlen; pt_out = NULL; ct_out = NULL; if (max > 0) { pt_out = (unsigned char *)calloc(1, max); ASSERT_NE(pt_out, nullptr); ct_out = (unsigned char *)calloc(1, max); ASSERT_NE(ct_out, nullptr); } rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, pt_out, ct, ctlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(pt_out, pt, ptlen) == 0); rc = zpc_aes_ecb_encrypt(aes_ecb, ct_out, pt, ptlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(ct_out, ct, ctlen) == 0); /* Unset key. */ rc = zpc_aes_ecb_set_key(aes_ecb, NULL); EXPECT_EQ(rc, 0); free(key); key = NULL; free(pt); pt = NULL; free(pt_out); pt_out = NULL; free(ct); ct = NULL; free(ct_out); ct_out = NULL; } } zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_ecb, rederive_protected_key1) { struct zpc_aes_key *aes_key1; struct zpc_aes_ecb *aes_ecb1, *aes_ecb2, *aes_ecb3; u8 m[96], c[96]; int rc, size; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb2); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb3); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb3, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); /* Random protected keys cannot rbe re-derived. */ rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb2, aes_key1); EXPECT_EQ(rc, 0); memset(aes_ecb2->param.protkey, 0, sizeof(aes_ecb2->param.protkey)); rc = zpc_aes_ecb_encrypt(aes_ecb2, c, m, 96); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_ecb_set_key(aes_ecb3, aes_key1); EXPECT_EQ(rc, 0); memset(aes_ecb3->param.protkey, 0, sizeof(aes_ecb3->param.protkey)); rc = zpc_aes_ecb_decrypt(aes_ecb3, m, c, 96); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); zpc_aes_ecb_free(&aes_ecb3); zpc_aes_ecb_free(&aes_ecb2); zpc_aes_ecb_free(&aes_ecb1); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_ecb3, nullptr); EXPECT_EQ(aes_ecb2, nullptr); EXPECT_EQ(aes_ecb1, nullptr); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_ecb, rederive_protected_key2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ecb *aes_ecb; unsigned int flags; int type, rc; const char *keystr = "605c4139c961b496ca5148f1bdb1bb1901f2101943a0ec10fcdc403d3b0c285a"; const char *msgstr = "68c9885ba2be03181f65f1e04e83d6ba6880467550bcf099be26dc9d9c0af15ab02abac07c116ac862a41da90cfa604f"; const char *ctstr = "a7603d29bbba4c77208bf2f3df9f5ec85204adce012299f2cce7b326ce78f5cf8040343dd291e8cf9f3645726368dc20"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_encrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_encrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_encrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_encrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_decrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_decrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(msg); free(ct); } TEST(aes_ecb, reencipher) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_ecb *aes_ecb; unsigned int flags; int type, rc; const char *keystr = "605c4139c961b496ca5148f1bdb1bb1901f2101943a0ec10fcdc403d3b0c285a"; const char *msgstr = "68c9885ba2be03181f65f1e04e83d6ba6880467550bcf099be26dc9d9c0af15ab02abac07c116ac862a41da90cfa604f"; const char *ctstr = "a7603d29bbba4c77208bf2f3df9f5ec85204adce012299f2cce7b326ce78f5cf8040343dd291e8cf9f3645726368dc20"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_encrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_encrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_encrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_encrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_decrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_decrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(msg); free(ct); } static void __task(struct zpc_aes_key *aes_key) { struct zpc_aes_ecb *aes_ecb; unsigned char buf[4096]; size_t msglen, ctlen; int rc, i; const char *msgstr = "68c9885ba2be03181f65f1e04e83d6ba6880467550bcf099be26dc9d9c0af15ab02abac07c116ac862a41da90cfa604f"; const char *ctstr = "a7603d29bbba4c77208bf2f3df9f5ec85204adce012299f2cce7b326ce78f5cf8040343dd291e8cf9f3645726368dc20"; u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); rc = zpc_aes_ecb_alloc(&aes_ecb); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_set_key(aes_ecb, aes_key); EXPECT_EQ(rc, 0); for (i = 0; i < 1000; i++) { /* Encrypt */ memcpy(buf, msg, msglen); memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_encrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_encrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_ecb->param.protkey, 0, sizeof(aes_ecb->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_ecb_decrypt(aes_ecb, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_ecb_decrypt(aes_ecb, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); } zpc_aes_ecb_free(&aes_ecb); EXPECT_EQ(aes_ecb, nullptr); free(msg); free(ct); } TEST(aes_ecb, threads) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; unsigned int flags; int type, rc, i; std::thread *t[500]; const char *keystr = "605c4139c961b496ca5148f1bdb1bb1901f2101943a0ec10fcdc403d3b0c285a"; u8 *key = testlib_hexstr2buf(keystr, &keylen); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); for (i = 0; i < 500; i++) { t[i] = new std::thread(__task, aes_key); } /* Do something with key object while threads are working with it. */ rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ for (i = 0; i < 500; i++) { memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ usleep(1); } for (i = 0; i < 500; i++) { t[i]->join(); delete t[i]; } zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); } libzpc-1.0.0/test/t_aes_gcm.cc000066400000000000000000001260771413160260300162130ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "gtest/gtest.h" #include "zpc/aes_gcm.h" #include "zpc/error.h" #include "aes_key_local.h" /* de-opaquify struct zpc_aes_key */ #include "aes_gcm_local.h" /* de-opaquify struct zpc_aes_gcm */ #include #include #include #include static void __run_json(const char *json); TEST(aes_gcm, alloc) { struct zpc_aes_gcm *aes_gcm; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_gcm_alloc(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); aes_gcm = NULL; rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); aes_gcm = (struct zpc_aes_gcm *)&aes_gcm; rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); } TEST(aes_gcm, free) { struct zpc_aes_gcm *aes_gcm; int rc; TESTLIB_ENV_AES_KEY_CHECK(); zpc_aes_gcm_free(NULL); aes_gcm = NULL; zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); } TEST(aes_gcm, set_key) { struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; u8 clearkey[32], iv[12]; unsigned int flags = 0; const char *mkvp, *apqns[257]; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, clearkey); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_gcm_set_key(NULL, aes_key); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_gcm_set_key(aes_gcm, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12); EXPECT_EQ(rc, 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_gcm, set_iv) { struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; const char *mkvp, *apqns[257]; u8 iv[16]; int rc, size, type; unsigned int flags; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(NULL, NULL, 0); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_gcm_set_iv(NULL, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_gcm_set_iv(aes_gcm, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 0); EXPECT_EQ(rc, ZPC_ERROR_IVSIZE); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, SIZE_MAX); EXPECT_EQ(rc, ZPC_ERROR_IVSIZE); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 16); EXPECT_EQ(rc, 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_gcm, encrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; const char *mkvp, *apqns[257]; u8 iv[12], aad[99], m[99], tag[12], c[99]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_gcm, decrypt) { struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; const char *mkvp, *apqns[257]; u8 iv[12], aad[99], m[99], tag[12], c[99]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_gcm, pc) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_gcm *aes_gcm1, *aes_gcm2; const char *mkvp, *apqns[257]; u8 iv[12], aad[99], m[99], tag[12], c[99], key[32], m_bak[99]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); memcpy(m_bak, m, 99); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm1, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm2, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm2, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_gcm_encrypt(aes_gcm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_gcm_encrypt(aes_gcm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); c[0] ^= 1; rc = zpc_aes_gcm_decrypt(aes_gcm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); rc = zpc_aes_gcm_encrypt(aes_gcm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_gcm_decrypt(aes_gcm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); memcpy(m_bak, m, 99); /* Random protected key */ rc = zpc_aes_gcm_set_key(aes_gcm1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm1, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm2, iv, 12); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_gcm_encrypt(aes_gcm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 99) == 0); rc = zpc_aes_gcm_encrypt(aes_gcm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); c[0] ^= 1; rc = zpc_aes_gcm_decrypt(aes_gcm1, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); rc = zpc_aes_gcm_encrypt(aes_gcm1, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, 0); tag[0] ^= 1; rc = zpc_aes_gcm_decrypt(aes_gcm2, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_TAGMISMATCH); zpc_aes_gcm_free(&aes_gcm2); zpc_aes_gcm_free(&aes_gcm1); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_gcm, stream_inplace_kat1) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; unsigned int flags; int type, rc; const char *keystr = "c4b03435b91fc52e09eff27e4dc3fb42"; const char *ivstr = "5046e7e08f0747e1efccb09e"; const char *aadstr = "75fc9078b488e9503dcb568c882c9eec24d80b04f0958c82aac8484f025c90434148db8e9bfe29c7e071b797457cb1695a5e5a6317b83690ba0538fb11e325ca"; const char *msgstr = "8e887b224e8b89c82e9a641cf579e6879e1111c7"; const char *ctstr = "b6786812574a254eb43b1cb1d1753564c6b520e9"; const char *tagstr = "ad8c09610d508f3d0f03cc523c0d5fcc"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, 32, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad + 32, aadlen - 31, NULL, 0); /* Works iff aadlen - 32 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG6RANGE); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad + 32, aadlen - 32, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, NULL, 0, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, mac, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, 32, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, aad + 32, aadlen - 32, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, NULL, 0, NULL, 0, buf + 16, msglen - 16); /* Works iff msglen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG8RANGE); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, mac, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad + 16, aadlen - 15, NULL, 0); /* Works iff aadlen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG6RANGE); rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, tag, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad + 16, aadlen - 16, NULL, 0); /* Works iff aadlen - 16 == 0 mod 16 */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, NULL, 0, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, NULL, 0, NULL, 0, buf + 16, msglen - 16); /* Works iff msglen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG8RANGE); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, tag, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_gcm, stream_inplace_kat2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; unsigned int flags; int type, rc; const char *keystr = "deb62233559b57476602b5adac57c77f"; const char *ivstr = "d084547de55bbc15"; const char *aadstr = ""; const char *msgstr = "d8986df0241ed3297582c0c239c724cb"; const char *ctstr = "03e1a168a7e377a913879b296a1b5f9c"; const char *tagstr = "3290aa95af505a742f517fabcc9b2094"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_EQ(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, aadlen, NULL, 0); /* Works iff aadlen == 0 mod 16 */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, NULL, 0, buf, msglen); /* Works iff msglen == 0 mod 16 */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, mac, taglen, NULL, 0, NULL, 0); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, aadlen, NULL, 0); /* Works iff aadlen == 0 mod 16 */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, NULL, 0, buf, msglen); /* Works iff msglen == 0 mod 16 */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, tag, taglen, NULL, 0, NULL, 0); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_gcm, wycheproof_kat) { TESTLIB_ENV_AES_KEY_CHECK(); __run_json("wycheproof/src/wycheproof/testvectors/aes_gcm_test.json"); } TEST(aes_gcm, nist_kat) { TESTLIB_ENV_AES_KEY_CHECK(); __run_json("nist_aes_gcm.json"); } static void __run_json(const char *json) { const char *tv = json, *str; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; unsigned int flags; u8 *key = NULL, *iv = NULL, *aad = NULL; u8 *pt = NULL, *pt_out = NULL, *ct = NULL, *ct_out = NULL; u8 *tag = NULL, *tag_out = NULL; int rc, tagsize = 0, ivsize = 0, keysize = 0; int valid = 0, ivlen0 = 0, deconly = 0; size_t aadlen, ptlen, ctlen, taglen, i, j, k, max; json_object *jkey, *jiv, *jtag, *jaad, *jmsg, *jct, *jresult, *jflags, *jtmp, *jtestgroups, *jfile, *jkeysize, *jivsize, *jtagsize, *jtests; json_bool b; int type; type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); jfile = json_object_from_file(tv); ASSERT_NE(jfile, nullptr); b = json_object_object_get_ex(jfile, "testGroups", &jtestgroups); ASSERT_TRUE(b); for (i = 0; i < (size_t)json_object_array_length(jtestgroups); i++) { jtmp = json_object_array_get_idx(jtestgroups, i); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "keySize", &jkeysize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "ivSize", &jivsize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tagSize", &jtagsize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tests", &jtests); ASSERT_TRUE(b); keysize = json_object_get_int(jkeysize); ivsize = json_object_get_int(jivsize); tagsize = json_object_get_int(jtagsize); rc = zpc_aes_key_set_size(aes_key, keysize); EXPECT_EQ(rc, 0); for (j = 0; j < (size_t)json_object_array_length(jtests); j++) { jtmp = json_object_array_get_idx(jtests, j); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "key", &jkey); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "iv", &jiv); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tag", &jtag); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "aad", &jaad); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "msg", &jmsg); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "ct", &jct); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "flags", &jflags); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "result", &jresult); ASSERT_TRUE(b); str = json_object_get_string(jkey); ASSERT_NE(str, nullptr); key = testlib_hexstr2buf(str, NULL); ASSERT_NE(key, nullptr); str = json_object_get_string(jiv); ASSERT_NE(str, nullptr); iv = testlib_hexstr2buf(str, NULL); str = json_object_get_string(jtag); ASSERT_NE(str, nullptr); tag = testlib_hexstr2buf(str, &taglen); ASSERT_NE(tag, nullptr); tag_out = (unsigned char *)calloc(1, taglen); ASSERT_NE(tag_out, nullptr); str = json_object_get_string(jaad); ASSERT_NE(str, nullptr); aad = testlib_hexstr2buf(str, &aadlen); str = json_object_get_string(jmsg); ASSERT_NE(str, nullptr); pt = testlib_hexstr2buf(str, &ptlen); str = json_object_get_string(jct); ASSERT_NE(str, nullptr); ct = testlib_hexstr2buf(str, &ctlen); str = json_object_get_string(jresult); ASSERT_NE(str, nullptr); if (strcmp(str, "valid") == 0 || strcmp(str, "acceptable") == 0) valid = 1; else valid = 0; for (k = 0; k < (size_t)json_object_array_length(jflags); k++) { jtmp = json_object_array_get_idx(jflags, k); ASSERT_NE(jtmp, nullptr); str = json_object_get_string(jtmp); if (strcmp(str, "ZeroLengthIv") == 0) ivlen0 = 1; else ivlen0 = 0; str = json_object_get_string(jtmp); if (strcmp(str, "DecryptOnly") == 0) deconly = 1; else deconly = 0; } max = ptlen > ctlen ? ptlen : ctlen; pt_out = NULL; ct_out = NULL; if (max > 0) { pt_out = (unsigned char *)calloc(1, max); ASSERT_NE(pt_out, nullptr); ct_out = (unsigned char *)calloc(1, max); ASSERT_NE(ct_out, nullptr); } rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm, ivlen0 ? (unsigned char *)1 : iv, ivsize / 8); EXPECT_EQ(rc, ivlen0 ? ZPC_ERROR_IVSIZE : 0); if (!ivlen0 && !deconly) { rc = zpc_aes_gcm_encrypt(aes_gcm, ct_out, tag_out, tagsize / 8, aad, aadlen, pt, ptlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(ct_out, ct, ctlen) == 0); if (valid) { EXPECT_TRUE(memcmp(tag_out, tag, tagsize / 8) == 0); } rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivsize / 8); EXPECT_EQ(rc, 0); } else if (!ivlen0) { rc = zpc_aes_gcm_decrypt(aes_gcm, pt_out, tag, tagsize / 8, aad, aadlen, ct, ctlen); EXPECT_EQ(rc, valid ? 0 : ZPC_ERROR_TAGMISMATCH); EXPECT_TRUE(memcmp(pt_out, pt, ptlen) == 0); } /* Unset key. */ rc = zpc_aes_gcm_set_key(aes_gcm, NULL); EXPECT_EQ(rc, 0); free(key); key = NULL; free(iv); iv = NULL; free(aad); aad = NULL; free(pt); pt = NULL; free(pt_out); pt_out = NULL; free(ct); ct = NULL; free(ct_out); ct_out = NULL; free(tag); tag = NULL; free(tag_out); tag_out = NULL; } } zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_gcm, rederive_protected_key1) { struct zpc_aes_key *aes_key1; struct zpc_aes_gcm *aes_gcm1, *aes_gcm2, *aes_gcm3; u8 iv[16], aad[99], m[99], tag[16], c[99]; /* use ivlen != 12 bytes such that it must be processed by kma */ int rc, size; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm2); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm3); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm1, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm2, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm3, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); /* Random protected keys cannot rbe re-derived. */ rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm1, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm1, iv, sizeof(iv)); EXPECT_EQ(rc, 0); memset(aes_gcm1->param.protkey, 0, sizeof(aes_gcm1->param.protkey)); rc = zpc_aes_gcm_set_iv(aes_gcm1, iv, sizeof(iv)); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_gcm_set_key(aes_gcm2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm2, iv, sizeof(iv)); EXPECT_EQ(rc, 0); memset(aes_gcm2->param.protkey, 0, sizeof(aes_gcm2->param.protkey)); rc = zpc_aes_gcm_encrypt(aes_gcm2, c, tag, 12, aad, 99, m, 99); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_gcm_set_key(aes_gcm3, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_iv(aes_gcm3, iv, sizeof(iv)); EXPECT_EQ(rc, 0); memset(aes_gcm3->param.protkey, 0, sizeof(aes_gcm3->param.protkey)); rc = zpc_aes_gcm_decrypt(aes_gcm3, m, tag, 12, aad, 99, c, 99); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_gcm_set_key(aes_gcm1, aes_key1); EXPECT_EQ(rc, 0); memset(aes_gcm1->param.protkey, 0, sizeof(aes_gcm1->param.protkey)); rc = zpc_aes_gcm_set_iv(aes_gcm1, iv, sizeof(iv)); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); zpc_aes_gcm_free(&aes_gcm3); zpc_aes_gcm_free(&aes_gcm2); zpc_aes_gcm_free(&aes_gcm1); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_gcm3, nullptr); EXPECT_EQ(aes_gcm2, nullptr); EXPECT_EQ(aes_gcm1, nullptr); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_gcm, rederive_protected_key2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; unsigned int flags; int type, rc; const char *keystr = "2034a82547276c83dd3212a813572bce"; const char *ivstr = "3254202d854734812398127a3d134421"; /* use ivlen != 12 bytes such that it must be processed by kma */ const char *aadstr = "1a0293d8f90219058902139013908190bc490890d3ff12a3"; const char *msgstr = "02efd2e5782312827ed5d230189a2a342b277ce048462193"; const char *ctstr = "64069c2d58690561f27ee199e6b479b6369eec688672bde9"; const char *tagstr = "9b7abadd6e69c1d9ec925786534f5075"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad + 16, aadlen - 15, NULL, 0); /* Works iff aadlen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG6RANGE); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, mac, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, NULL, 0, NULL, 0, buf + 16, msglen - 16); /* Works iff msglen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG8RANGE); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, mac, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad + 16, aadlen - 15, NULL, 0); /* Works iff aadlen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG6RANGE); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, tag, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, NULL, 0, NULL, 0, buf + 16, msglen - 16); /* Works iff msglen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG8RANGE); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, tag, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_gcm, reencipher) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen, taglen, aadlen; unsigned char buf[4096], mac[16]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; struct zpc_aes_gcm *aes_gcm; unsigned int flags; int type, rc; const char *keystr = "2034a82547276c83dd3212a813572bce"; const char *ivstr = "3254202d854734812398127a3d134421"; /* use ivlen != 12 bytes such that it must be processed by kma */ const char *aadstr = "1a0293d8f90219058902139013908190bc490890d3ff12a3"; const char *msgstr = "02efd2e5782312827ed5d230189a2a342b277ce048462193"; const char *ctstr = "64069c2d58690561f27ee199e6b479b6369eec688672bde9"; const char *tagstr = "9b7abadd6e69c1d9ec925786534f5075"; u8 *key = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key, nullptr); u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad + 16, aadlen - 15, NULL, 0); /* Works iff aadlen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG6RANGE); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, mac, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, NULL, 0, NULL, 0, buf + 16, msglen - 16); /* Works iff msglen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG8RANGE); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, mac, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad + 16, aadlen - 15, NULL, 0); /* Works iff aadlen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG6RANGE); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, tag, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, NULL, 0, NULL, 0, buf + 16, msglen - 16); /* Works iff msglen - 16 == 0 mod 16 */ EXPECT_EQ(rc, ZPC_ERROR_ARG8RANGE); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, tag, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); free(iv); free(aad); free(msg); free(ct); free(tag); } static void __task(struct zpc_aes_key *aes_key) { struct zpc_aes_gcm *aes_gcm; unsigned char buf[4096], mac[16]; size_t ivlen, msglen, ctlen, taglen, aadlen; int rc, i; const char *ivstr = "3254202d854734812398127a3d134421"; /* use ivlen != 12 bytes such that it must be processed by kma */ const char *aadstr = "1a0293d8f90219058902139013908190bc490890d3ff12a3"; const char *msgstr = "02efd2e5782312827ed5d230189a2a342b277ce048462193"; const char *ctstr = "64069c2d58690561f27ee199e6b479b6369eec688672bde9"; const char *tagstr = "9b7abadd6e69c1d9ec925786534f5075"; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *aad = testlib_hexstr2buf(aadstr, &aadlen); ASSERT_NE(aad, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); u8 *tag = testlib_hexstr2buf(tagstr, &taglen); ASSERT_NE(tag, nullptr); rc = zpc_aes_gcm_alloc(&aes_gcm); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_set_key(aes_gcm, aes_key); EXPECT_EQ(rc, 0); for (i = 0; i < 1000; i++) { /* Encrypt */ memcpy(buf, msg, msglen); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_encrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_encrypt(aes_gcm, buf + 16, mac, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); EXPECT_TRUE(memcmp(mac, tag, taglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_gcm_set_iv(aes_gcm, iv, ivlen); EXPECT_EQ(rc, 0); memset(aes_gcm->param.protkey, 0, sizeof(aes_gcm->param.protkey)); /* force WKaVP mismatch */ rc = zpc_aes_gcm_decrypt(aes_gcm, NULL, NULL, 0, aad, 16, NULL, 0); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf, NULL, 0, aad + 16, aadlen - 16, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_gcm_decrypt(aes_gcm, buf + 16, tag, taglen, NULL, 0, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); } zpc_aes_gcm_free(&aes_gcm); EXPECT_EQ(aes_gcm, nullptr); free(iv); free(aad); free(msg); free(ct); free(tag); } TEST(aes_gcm, threads) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key; unsigned int flags; int type, rc, i; std::thread *t[500]; const char *keystr = "2034a82547276c83dd3212a813572bce"; u8 *key = testlib_hexstr2buf(keystr, &keylen); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); for (i = 0; i < 500; i++) { t[i] = new std::thread(__task, aes_key); } /* Do something with key object while threads are working with it. */ rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key->cur, 0, sizeof(aes_key->cur)); /* destroy current secure key */ for (i = 0; i < 500; i++) { memset(&aes_key->prot, 0, sizeof(aes_key->prot)); /* destroy cached protected key */ usleep(1); } for (i = 0; i < 500; i++) { t[i]->join(); delete t[i]; } zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); free(key); } libzpc-1.0.0/test/t_aes_key.cc000066400000000000000000000334551413160260300162320ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "gtest/gtest.h" #include "zpc/aes_key.h" #include "zpc/error.h" TEST(aes_key, alloc) { struct zpc_aes_key *aes_key; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_key_alloc(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); aes_key = NULL; rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); aes_key = (struct zpc_aes_key *)&aes_key; rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, free) { struct zpc_aes_key *aes_key; int rc; TESTLIB_ENV_AES_KEY_CHECK(); zpc_aes_key_free(NULL); aes_key = NULL; zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, set_keysize) { struct zpc_aes_key *aes_key; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(NULL, -1); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_size(NULL, 0); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_size(NULL, 1); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_size(NULL, 128); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_size(NULL, 192); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_size(NULL, 256); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_size(aes_key, -1); EXPECT_EQ(rc, ZPC_ERROR_KEYSIZE); rc = zpc_aes_key_set_size(aes_key, 0); EXPECT_EQ(rc, ZPC_ERROR_KEYSIZE); rc = zpc_aes_key_set_size(aes_key, 1); EXPECT_EQ(rc, ZPC_ERROR_KEYSIZE); rc = zpc_aes_key_set_size(aes_key, 128); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, 192); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, 256); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, set_type) { struct zpc_aes_key *aes_key; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(NULL, -1); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_type(NULL, 0); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_type(NULL, ZPC_AES_KEY_TYPE_CCA_DATA); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_type(NULL, ZPC_AES_KEY_TYPE_CCA_CIPHER); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_type(NULL, ZPC_AES_KEY_TYPE_EP11); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_type(NULL, 4); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_type(aes_key, -1); EXPECT_EQ(rc, ZPC_ERROR_KEYTYPE); rc = zpc_aes_key_set_type(aes_key, 0); EXPECT_EQ(rc, ZPC_ERROR_KEYTYPE); rc = zpc_aes_key_set_type(aes_key, ZPC_AES_KEY_TYPE_CCA_DATA); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, ZPC_AES_KEY_TYPE_CCA_CIPHER); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, ZPC_AES_KEY_TYPE_EP11); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, 4); EXPECT_EQ(rc, ZPC_ERROR_KEYTYPE); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, set_flags) { struct zpc_aes_key *aes_key; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(NULL, 0); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_flags(aes_key, -1); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, set_mkvp) { struct zpc_aes_key *aes_key; const char *mkvp; unsigned int flags; int rc, type; TESTLIB_ENV_AES_KEY_CHECK(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_mkvp(NULL, mkvp); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_mkvp(aes_key, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, ZPC_ERROR_KEYTYPENOTSET); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, set_apqns) { struct zpc_aes_key *aes_key; const char *apqns[] = {"01.0037", "\n01.0037\t ", NULL}; /* apqn example */ int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_apqns(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_apqns(NULL, apqns); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_set_apqns(aes_key, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, import_clear_1) { struct zpc_aes_key *aes_key; const u8 key[32] = {0}; const char *apqns[257]; unsigned int flags; int rc, type, size; const char *mkvp; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_import_clear(NULL, key); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_import_clear(aes_key, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG2NULL); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, ZPC_ERROR_APQNSNOTSET); if (mkvp == NULL) { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, ZPC_ERROR_KEYSIZENOTSET); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); if (mkvp == NULL) { rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, ZPC_ERROR_KEYTYPENOTSET); } rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_import_clear(aes_key, key); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, import_clear_2) { struct zpc_aes_key *aes_key; u8 clearkey[32]; const char *apqns[257]; unsigned int flags; int rc, size, type; const char *mkvp; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags= testlib_env_aes_key_type(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); /* mkvp */ rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_import_clear(aes_key, clearkey); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, generate_1) { struct zpc_aes_key *aes_key; unsigned int flags; const char *apqns[257]; int rc, size, type; const char *mkvp; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags= testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYSIZENOTSET); if (mkvp == NULL) { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYSIZENOTSET); } rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); if (mkvp == NULL) { rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, ZPC_ERROR_KEYTYPENOTSET); } rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, generate_2) { struct zpc_aes_key *aes_key; unsigned int flags; const char *apqns[257]; int rc, size, type; const char *mkvp; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags= testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, reencipher) { struct zpc_aes_key *aes_key; unsigned int flags; const char *apqns[257]; int rc, size, type; const char *mkvp; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags= testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_reencipher(aes_key, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, export) { struct zpc_aes_key *aes_key; u8 buf[10000]; unsigned int flags; const char *apqns[257]; int rc, size, type; size_t buflen; const char *mkvp; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags= testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_export(NULL, NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_export(aes_key, NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG3NULL); rc = zpc_aes_key_export(aes_key, NULL, &buflen); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); buflen = 0; rc = zpc_aes_key_export(aes_key, buf, &buflen); EXPECT_EQ(rc, ZPC_ERROR_SMALLOUTBUF); rc = zpc_aes_key_export(aes_key, NULL, &buflen); EXPECT_EQ(rc, 0); EXPECT_GT(buflen, 0UL); rc = zpc_aes_key_export(aes_key, buf, &buflen); EXPECT_EQ(rc, 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); } TEST(aes_key, import) { struct zpc_aes_key *aes_key, *aes_key2; u8 buf[10000], buf2[10000]; unsigned int flags; const char *apqns[257]; int rc, size, type; size_t buflen = sizeof(buf); size_t buf2len = sizeof(buf2); const char *mkvp; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags= testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import(NULL, NULL, 0); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_key_import(aes_key, NULL, 0); EXPECT_EQ(rc, ZPC_ERROR_ARG2NULL); rc = zpc_aes_key_import(aes_key, buf, 63); EXPECT_EQ(rc, ZPC_ERROR_ARG3RANGE); rc = zpc_aes_key_import(aes_key, buf, 630); EXPECT_EQ(rc, ZPC_ERROR_ARG3RANGE); rc = zpc_aes_key_set_size(aes_key, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import(aes_key, buf, 64); EXPECT_EQ(rc, ZPC_ERROR_KEYTYPENOTSET); rc = zpc_aes_key_set_type(aes_key, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key, mkvp); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key, apqns); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_export(aes_key, buf, &buflen); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import(aes_key2, buf, buflen); EXPECT_EQ(rc, 0); rc = zpc_aes_key_export(aes_key2, buf2, &buf2len); EXPECT_EQ(rc, 0); EXPECT_EQ(buf2len, buflen); EXPECT_TRUE(memcmp(buf2, buf, buflen) == 0); zpc_aes_key_free(&aes_key); EXPECT_EQ(aes_key, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); } libzpc-1.0.0/test/t_aes_xts.cc000066400000000000000000001215321413160260300162520ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "gtest/gtest.h" #include "zpc/aes_xts.h" #include "zpc/error.h" #include "aes_key_local.h" /* de-opaquify struct zpc_aes_key */ #include "aes_xts_local.h" /* de-opaquify struct zpc_aes_xts */ #include #include #include #include static void __run_json(const char *json); TEST(aes_xts, alloc) { struct zpc_aes_xts *aes_xts; int rc; TESTLIB_ENV_AES_KEY_CHECK(); rc = zpc_aes_xts_alloc(NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); aes_xts = NULL; rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); aes_xts = (struct zpc_aes_xts *)&aes_xts; rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); } TEST(aes_xts, free) { struct zpc_aes_xts *aes_xts; int rc; TESTLIB_ENV_AES_KEY_CHECK(); zpc_aes_xts_free(NULL); aes_xts = NULL; zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); } TEST(aes_xts, set_key) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; u8 clearkey1[32], clearkey2[32], iv[16]; unsigned int flags = 0; const char *mkvp, *apqns[257]; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, clearkey1); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, clearkey2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(NULL, NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_xts_set_key(NULL, aes_key1, aes_key2); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_xts_set_key(aes_xts, NULL, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, NULL, aes_key1); EXPECT_EQ(rc, 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); } TEST(aes_xts, set_iv) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; const char *mkvp, *apqns[257]; u8 iv[16]; int rc, size, type; unsigned int flags; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(NULL, NULL); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_xts_set_iv(NULL, iv); EXPECT_EQ(rc, ZPC_ERROR_ARG1NULL); rc = zpc_aes_xts_set_iv(aes_xts, NULL); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_generate(aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, ZPC_ERROR_KEYNOTSET); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); } TEST(aes_xts, encrypt) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; const char *mkvp, *apqns[257]; u8 iv[16], m[64], c[64]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts, c, m, 64); EXPECT_EQ(rc, 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); } TEST(aes_xts, decrypt) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; const char *mkvp, *apqns[257]; u8 iv[16], m[64], c[64]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts, m, c, 64); EXPECT_EQ(rc, 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); } TEST(aes_xts, pc) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts1, *aes_xts2; const char *mkvp, *apqns[257]; u8 iv[16], m[96], c[96], key[32], m_bak[96]; unsigned int flags; int rc, size, type; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); memcpy(m_bak, m, 96); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts1); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts1, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts1, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts2, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts2, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_xts_encrypt(aes_xts2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_xts_encrypt(aes_xts2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_xts_encrypt(aes_xts1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); /* Random protected key */ rc = zpc_aes_xts_set_key(aes_xts1, NULL, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts2, NULL, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key2, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts1, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts1, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts2, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts2, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_xts_encrypt(aes_xts2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_xts_encrypt(aes_xts2, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts1, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); rc = zpc_aes_xts_encrypt(aes_xts1, c, m, 96); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts2, m, c, 96); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(m, m_bak, 96) == 0); zpc_aes_xts_free(&aes_xts2); zpc_aes_xts_free(&aes_xts1); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_xts, stream_inplace_kat1) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen, ivlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; unsigned int flags; int type, rc; const char *keystr = "88dfd7c83cb121968feb417520555b36c0f63b662570eac12ea96cbe188ad5b1a44db23ac6470316cba0041cadf248f6d9a7713f454e663f3e3987585cebbf96"; const char *ivstr = "0ee84632b838dd528f1d96c76439805c"; const char *msgstr = "ec36551c70efcdf85de7a39988978263ad261e83996dad219a0058e02187384f2d0754ff9cfa000bec448fafd2cfa738"; const char *ctstr = "a55d533c9c5885562b92d4582ea69db8e2ba9c0b967a9f0167700b043525a47bafe7d630774eaf4a1dc9fbcf94a1fda4"; u8 *key1 = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key1, nullptr); keylen /= 2; u8 *key2 = key1 + keylen; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key2); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, 16); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts, buf + 16, buf + 16, msglen - 16); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); free(key1); free(iv); free(msg); free(ct); } TEST(aes_xts, stream_inplace_kat2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, ivlen, msglen, ctlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; unsigned int flags; int type, rc; const char *keystr = "394c97881abd989d29c703e48a72b397a7acf51b59649eeea9b33274d8541df4"; const char *ivstr = "4b15c684a152d485fe9937d39b168c29"; const char *msgstr = "2f3b9dcfbae729583b1d1ffdd16bb6fe2757329435662a78f0"; const char *ctstr = "f3473802e38a3ffef4d4fb8e6aa266ebde553a64528a06463e"; u8 *key1 = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key1, nullptr); keylen /= 2; u8 *key2 = key1 + keylen; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, ctlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); free(key1); free(iv); free(msg); free(ct); } TEST(aes_xts, nist_kat) { TESTLIB_ENV_AES_KEY_CHECK(); __run_json("nist_aes_xts.json"); } static void __run_json(const char *json) { const char *tv = json, *str; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; unsigned int flags; u8 *key1 = NULL, *key2 = NULL, *iv = NULL; u8 *pt = NULL, *pt_out = NULL, *ct = NULL, *ct_out = NULL; int rc, keysize = 0; size_t ptlen, ctlen, i, j, max; json_object *jkey, *jiv, *jmsg, *jct, *jtmp, *jtestgroups, *jfile, *jkeysize, *jtests; json_bool b; int type; type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); jfile = json_object_from_file(tv); ASSERT_NE(jfile, nullptr); b = json_object_object_get_ex(jfile, "testGroups", &jtestgroups); ASSERT_TRUE(b); for (i = 0; i < (size_t)json_object_array_length(jtestgroups); i++) { jtmp = json_object_array_get_idx(jtestgroups, i); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "keySize", &jkeysize); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "tests", &jtests); ASSERT_TRUE(b); keysize = json_object_get_int(jkeysize); rc = zpc_aes_key_set_size(aes_key1, keysize); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, keysize); EXPECT_EQ(rc, 0); for (j = 0; j < (size_t)json_object_array_length(jtests); j++) { jtmp = json_object_array_get_idx(jtests, j); ASSERT_NE(jtmp, nullptr); b = json_object_object_get_ex(jtmp, "key", &jkey); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "iv", &jiv); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "msg", &jmsg); ASSERT_TRUE(b); b = json_object_object_get_ex(jtmp, "ct", &jct); ASSERT_TRUE(b); str = json_object_get_string(jkey); ASSERT_NE(str, nullptr); key1 = testlib_hexstr2buf(str, NULL); ASSERT_NE(key1, nullptr); key2 = key1 + (keysize / 8); str = json_object_get_string(jiv); ASSERT_NE(str, nullptr); iv = testlib_hexstr2buf(str, NULL); str = json_object_get_string(jmsg); ASSERT_NE(str, nullptr); pt = testlib_hexstr2buf(str, &ptlen); str = json_object_get_string(jct); ASSERT_NE(str, nullptr); ct = testlib_hexstr2buf(str, &ctlen); max = ptlen > ctlen ? ptlen : ctlen; pt_out = NULL; ct_out = NULL; if (max > 0) { pt_out = (unsigned char *)calloc(1, max); ASSERT_NE(pt_out, nullptr); ct_out = (unsigned char *)calloc(1, max); ASSERT_NE(ct_out, nullptr); } rc = zpc_aes_key_import_clear(aes_key1, key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_encrypt(aes_xts, ct_out, pt, ptlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(ct_out, ct, ctlen) == 0); rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_decrypt(aes_xts, pt_out, ct, ctlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(pt_out, pt, ptlen) == 0); /* Unset key. */ rc = zpc_aes_xts_set_key(aes_xts, NULL, NULL); EXPECT_EQ(rc, 0); free(key1); key1 = NULL; free(iv); iv = NULL; free(pt); pt = NULL; free(pt_out); pt_out = NULL; free(ct); ct = NULL; free(ct_out); ct_out = NULL; } } zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); } TEST(aes_xts, rederive_protected_key1) { struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts1, *aes_xts2, *aes_xts3; u8 iv[16], m[96], c[96]; int rc, size; TESTLIB_ENV_AES_KEY_CHECK(); size = testlib_env_aes_key_size(); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts1); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts3); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts1, NULL, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts2, NULL, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts3, NULL, NULL); /* Unset key. */ EXPECT_EQ(rc, 0); /* Random protected keys cannot be re-derived. */ rc = zpc_aes_key_set_mkvp(aes_key1, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_mkvp(aes_key2, NULL); /* Unset apqns. */ EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, size); EXPECT_EQ(rc, 0); rc = zpc_aes_key_generate(aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts1, aes_key1, aes_key2); EXPECT_EQ(rc, 0); memset(aes_xts1->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts1->aes_key2->keysize)); rc = zpc_aes_xts_set_iv(aes_xts1, iv); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_xts_set_key(aes_xts2, aes_key2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts2, iv); EXPECT_EQ(rc, 0); memset(aes_xts2->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts2->aes_key1->keysize)); rc = zpc_aes_xts_encrypt(aes_xts2, c, m, 96); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); rc = zpc_aes_xts_set_key(aes_xts3, aes_key2, aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_iv(aes_xts3, iv); EXPECT_EQ(rc, 0); memset(aes_xts3->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts3->aes_key1->keysize)); rc = zpc_aes_xts_decrypt(aes_xts3, m, c, 96); EXPECT_EQ(rc, ZPC_ERROR_PROTKEYONLY); zpc_aes_xts_free(&aes_xts3); zpc_aes_xts_free(&aes_xts2); zpc_aes_xts_free(&aes_xts1); zpc_aes_key_free(&aes_key2); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_xts3, nullptr); EXPECT_EQ(aes_xts2, nullptr); EXPECT_EQ(aes_xts1, nullptr); EXPECT_EQ(aes_key2, nullptr); EXPECT_EQ(aes_key1, nullptr); } TEST(aes_xts, rederive_protected_key2) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen, ivlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; unsigned int flags; int type, rc; const char *keystr = "394c97881abd989d29c703e48a72b397a7acf51b59649eeea9b33274d8541df4"; const char *ivstr = "4b15c684a152d485fe9937d39b168c29"; const char *msgstr = "2f3b9dcfbae729583b1d1ffdd16bb6fe2757329435662a78f0"; const char *ctstr = "f3473802e38a3ffef4d4fb8e6aa266ebde553a64528a06463e"; u8 *key1 = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key1, nullptr); keylen /= 2; u8 *key2 = key1 + keylen; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key2); EXPECT_EQ(rc, 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); free(key1); free(iv); free(msg); free(ct); } TEST(aes_xts, reencipher) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen, msglen, ctlen, ivlen; unsigned char buf[4096]; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key1, *aes_key2; struct zpc_aes_xts *aes_xts; unsigned int flags; int type, rc; const char *keystr = "394c97881abd989d29c703e48a72b397a7acf51b59649eeea9b33274d8541df4"; const char *ivstr = "4b15c684a152d485fe9937d39b168c29"; const char *msgstr = "2f3b9dcfbae729583b1d1ffdd16bb6fe2757329435662a78f0"; const char *ctstr = "f3473802e38a3ffef4d4fb8e6aa266ebde553a64528a06463e"; u8 *key1 = testlib_hexstr2buf(keystr, &keylen); ASSERT_NE(key1, nullptr); keylen /= 2; u8 *key2 = key1 + keylen; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_reencipher(aes_key1, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key1->cur, 0, sizeof(aes_key1->cur)); /* destroy current secure key */ rc = zpc_aes_key_reencipher(aes_key2, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key2->cur, 0, sizeof(aes_key2->cur)); /* destroy current secure key */ /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Encrypt */ memcpy(buf, msg, msglen); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); free(key1); free(iv); free(msg); free(ct); } static void __task(struct zpc_aes_key *aes_key1, struct zpc_aes_key *aes_key2) { struct zpc_aes_xts *aes_xts; unsigned char buf[4096]; size_t ivlen, msglen, ctlen; int rc, i; const char *ivstr = "4b15c684a152d485fe9937d39b168c29"; const char *msgstr = "2f3b9dcfbae729583b1d1ffdd16bb6fe2757329435662a78f0"; const char *ctstr = "f3473802e38a3ffef4d4fb8e6aa266ebde553a64528a06463e"; u8 *iv = testlib_hexstr2buf(ivstr, &ivlen); ASSERT_NE(iv, nullptr); u8 *msg = testlib_hexstr2buf(msgstr, &msglen); ASSERT_NE(msg, nullptr); u8 *ct = testlib_hexstr2buf(ctstr, &ctlen); ASSERT_NE(ct, nullptr); rc = zpc_aes_xts_alloc(&aes_xts); EXPECT_EQ(rc, 0); rc = zpc_aes_xts_set_key(aes_xts, aes_key1, aes_key2); EXPECT_EQ(rc, 0); for (i = 0; i < 1000; i++) { /* Encrypt */ memcpy(buf, msg, msglen); memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_encrypt(aes_xts, buf, buf, ctlen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, ct, ctlen) == 0); /* Decrypt */ memcpy(buf, ct, ctlen); memset(aes_xts->param_pcc, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key2->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_set_iv(aes_xts, iv); EXPECT_EQ(rc, 0); memset(aes_xts->param_km, 0, AES_XTS_PROTKEYLEN(aes_xts->aes_key1->keysize)); /* force WKaVP mismatch */ rc = zpc_aes_xts_decrypt(aes_xts, buf, buf, msglen); EXPECT_EQ(rc, 0); EXPECT_TRUE(memcmp(buf, msg, msglen) == 0); } zpc_aes_xts_free(&aes_xts); EXPECT_EQ(aes_xts, nullptr); free(iv); free(msg); free(ct); } TEST(aes_xts, threads) { TESTLIB_ENV_AES_KEY_CHECK(); size_t keylen; const char *mkvp, *apqns[257]; struct zpc_aes_key *aes_key1, *aes_key2; unsigned int flags; int type, rc, i; std::thread *t[500]; const char *keystr = "394c97881abd989d29c703e48a72b397a7acf51b59649eeea9b33274d8541df4"; u8 *key1 = testlib_hexstr2buf(keystr, &keylen); keylen /= 2; u8 *key2 = key1 + keylen; type = testlib_env_aes_key_type(); flags = testlib_env_aes_key_flags(); mkvp = testlib_env_aes_key_mkvp(); (void)testlib_env_aes_key_apqns(apqns); rc = zpc_aes_key_alloc(&aes_key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_alloc(&aes_key2); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key1, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key1, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key1, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key1, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key1, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key1, key1); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_type(aes_key2, type); EXPECT_EQ(rc, 0); if (mkvp != NULL) { rc = zpc_aes_key_set_mkvp(aes_key2, mkvp); EXPECT_EQ(rc, 0); } else { rc = zpc_aes_key_set_apqns(aes_key2, apqns); EXPECT_EQ(rc, 0); } rc = zpc_aes_key_set_flags(aes_key2, flags); EXPECT_EQ(rc, 0); rc = zpc_aes_key_set_size(aes_key2, keylen * 8); EXPECT_EQ(rc, 0); rc = zpc_aes_key_import_clear(aes_key2, key2); EXPECT_EQ(rc, 0); for (i = 0; i < 500; i++) { t[i] = new std::thread(__task, aes_key1, aes_key2); } /* Do something with key object while threads are working with it. */ rc = zpc_aes_key_reencipher(aes_key1, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key1->cur, 0, sizeof(aes_key1->cur)); /* destroy current secure key */ rc = zpc_aes_key_reencipher(aes_key2, ZPC_AES_KEY_REENCIPHER_CURRENT_TO_NEW); EXPECT_EQ(rc, 0); memset(&aes_key2->cur, 0, sizeof(aes_key2->cur)); /* destroy current secure key */ for (i = 0; i < 500; i++) { memset(&aes_key1->prot, 0, sizeof(aes_key1->prot)); /* destroy cached protected key */ usleep(1); memset(&aes_key2->prot, 0, sizeof(aes_key2->prot)); /* destroy cached protected key */ } for (i = 0; i < 500; i++) { t[i]->join(); delete t[i]; } zpc_aes_key_free(&aes_key1); EXPECT_EQ(aes_key1, nullptr); zpc_aes_key_free(&aes_key2); EXPECT_EQ(aes_key2, nullptr); free(key1); } libzpc-1.0.0/test/t_environment.cc000066400000000000000000000014641413160260300171510ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "gtest/gtest.h" #include "testlib.h" #include "zpc/aes_key.h" #include /* * Check for invalid test environment variable values. * Unset environment variables are ignored. The corresponding tests are * skipped later. */ /* * Check environment variables for test cases * that use zpc_aes_key objects. */ TEST(environment, test_aes_key) { int size; size = testlib_env_aes_key_size(); switch(size) { case -1: /* fall-through */ case 128: /* fall-through */ case 192: /* fall-through */ case 256: /* fall-through */ break; default: ASSERT_TRUE(size == 128 || size == 192 || size == 256); break; } } libzpc-1.0.0/test/t_error.cc000066400000000000000000000010511413160260300157260ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "gtest/gtest.h" #include "zpc/error.h" #include #include TEST(error, string) { const char *errstr; errstr = zpc_error_string(0); EXPECT_TRUE(strcmp(errstr, "success") == 0); errstr = zpc_error_string(-1); EXPECT_TRUE(strcmp(errstr, "undefined error code") == 0); errstr = zpc_error_string(50); EXPECT_TRUE(strcmp(errstr, "LAST") == 0); } libzpc-1.0.0/test/t_system.cc000066400000000000000000000014151413160260300161250ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "gtest/gtest.h" #include #include #include #include #include TEST(system, platform) { const union { long _; char little; } is_endian = { 1 }; EXPECT_TRUE(sizeof(char) == 1); EXPECT_TRUE(sizeof(short) == 2); EXPECT_TRUE(sizeof(int) == 4); EXPECT_TRUE(sizeof(size_t) == 8); EXPECT_TRUE(sizeof(long) == 8); EXPECT_TRUE(sizeof(long long) == 8); EXPECT_FALSE(is_endian.little); } TEST(system, dev_pkey) { int pkeyfd; EXPECT_GE(pkeyfd = open("/dev/pkey", O_RDWR), 0); if (pkeyfd >= 0) { close(pkeyfd); pkeyfd = -1; } } libzpc-1.0.0/test/t_testlib.cc000066400000000000000000000165161413160260300162570ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "gtest/gtest.h" #include "testlib.h" #include "zpc/aes_key.h" #include #include #include TEST(testlib, env_aes_key_mkvp) { const char *oldenv = NULL, *mkvp; int rc; /* Safe envoronment. */ oldenv = getenv("ZPC_TEST_AES_KEY_MKVP"); rc = setenv("ZPC_TEST_AES_KEY_MKVP", "abcde", 1); ASSERT_EQ(rc, 0); mkvp = testlib_env_aes_key_mkvp(); EXPECT_TRUE(strcmp(mkvp, "abcde") == 0); rc = unsetenv("ZPC_TEST_AES_KEY_MKVP"); ASSERT_EQ(rc, 0); mkvp = testlib_env_aes_key_mkvp(); EXPECT_EQ(mkvp, nullptr); if (oldenv != NULL) { /* Restore environment. */ rc = setenv("ZPC_TEST_AES_KEY_MKVP", oldenv, 1); ASSERT_EQ(rc, 0); } } TEST(testlib, env_aes_key_apqns) { const char *oldenv = NULL; const char *apqns[257]; int rc; /* Safe envoronment. */ oldenv = getenv("ZPC_TEST_AES_KEY_APQNS"); rc = setenv("ZPC_TEST_AES_KEY_APQNS", "abcde fg\nhi\tj,k \n\t, l", 1); ASSERT_EQ(rc, 0); rc = testlib_env_aes_key_apqns(apqns); EXPECT_TRUE(strcmp(apqns[0], "abcde") == 0); EXPECT_TRUE(strcmp(apqns[1], "fg") == 0); EXPECT_TRUE(strcmp(apqns[2], "hi") == 0); EXPECT_TRUE(strcmp(apqns[3], "j") == 0); EXPECT_TRUE(strcmp(apqns[4], "k") == 0); EXPECT_TRUE(strcmp(apqns[5], "l") == 0); EXPECT_EQ(apqns[6], nullptr); rc = unsetenv("ZPC_TEST_AES_KEY_APQNS"); ASSERT_EQ(rc, 0); rc = testlib_env_aes_key_apqns(apqns); EXPECT_EQ(rc, -1); if (oldenv != NULL) { /* Restore environment. */ rc = setenv("ZPC_TEST_AES_KEY_APQNS", oldenv, 1); ASSERT_EQ(rc, 0); } } TEST(testlib, env_aes_key_size) { const char *oldenv = NULL; int rc, size; size_t i; struct { const char *sizestr; const int sizeint; } kat[] = { { "", -1 }, { "abcde", -1 }, { "-2147483649", /* -max(4 byte int) - 2 = -2^31 - 1 */ -1 }, { "2147483648", /* max(4 byte int) + 1 = 2^31 */ -1 }, { "-1", -1 }, { "-0xa", -10 }, { "-0XFf", -255 }, { "-011", -9 }, { "256", 256 }, { "0xB", 11 }, { "0XfF", 255 }, { "012", 10 } }; /* Safe envoronment. */ oldenv = getenv("ZPC_TEST_AES_KEY_SIZE"); for (i = 0; i < NMEMB(kat); i++) { rc = setenv("ZPC_TEST_AES_KEY_SIZE", kat[i].sizestr, 1); ASSERT_EQ(rc, 0); size = testlib_env_aes_key_size(); EXPECT_EQ(size, kat[i].sizeint); rc = unsetenv("ZPC_TEST_AES_KEY_SIZE"); ASSERT_EQ(rc, 0); } if (oldenv != NULL) { /* Restore environment. */ rc = setenv("ZPC_TEST_AES_KEY_SIZE", oldenv, 1); ASSERT_EQ(rc, 0); } } TEST(testlib, env_aes_key_type) { const char *oldenv = NULL; int rc, type; /* Safe envoronment. */ oldenv = getenv("ZPC_TEST_AES_KEY_TYPE"); rc = setenv("ZPC_TEST_AES_KEY_TYPE", "abcde", 1); ASSERT_EQ(rc, 0); type = testlib_env_aes_key_type(); EXPECT_EQ(type, -1); rc = unsetenv("ZPC_TEST_AES_KEY_TYPE"); ASSERT_EQ(rc, 0); rc = setenv("ZPC_TEST_AES_KEY_TYPE", "ZPC_AES_KEY_TYPE_CCA_DATA", 1); ASSERT_EQ(rc, 0); type = testlib_env_aes_key_type(); EXPECT_EQ(type, ZPC_AES_KEY_TYPE_CCA_DATA); rc = unsetenv("ZPC_TEST_AES_KEY_TYPE"); ASSERT_EQ(rc, 0); rc = setenv("ZPC_TEST_AES_KEY_TYPE", "ZPC_AES_KEY_TYPE_CCA_CIPHER", 1); ASSERT_EQ(rc, 0); type = testlib_env_aes_key_type(); EXPECT_EQ(type, ZPC_AES_KEY_TYPE_CCA_CIPHER); rc = unsetenv("ZPC_TEST_AES_KEY_TYPE"); ASSERT_EQ(rc, 0); rc = setenv("ZPC_TEST_AES_KEY_TYPE", "ZPC_AES_KEY_TYPE_EP11", 1); ASSERT_EQ(rc, 0); type = testlib_env_aes_key_type(); EXPECT_EQ(type, ZPC_AES_KEY_TYPE_EP11); rc = unsetenv("ZPC_TEST_AES_KEY_TYPE"); ASSERT_EQ(rc, 0); if (oldenv != NULL) { /* Restore environment. */ rc = setenv("ZPC_TEST_AES_KEY_TYPE", oldenv, 1); ASSERT_EQ(rc, 0); } } TEST(testlib, env_aes_key_flags) { const char *oldenv = NULL; int rc; unsigned int flags; size_t i; struct { const char *flagsstr; const unsigned int flagsint; } kat[] = { { "", 0 }, { "abcde", 0 }, { "-4294967297", /* max(4 byte uint) - 1 = -2^32 - 1 */ 0 }, { "4294967296", /* max(4 byte int) + 1 = 2^32 */ 0 }, { "-1", 0 }, { "-0xa", 0 }, { "-0XFf", 0 }, { "-011", 0 }, { "256", 256 }, { "0xB", 11 }, { "0XfF", 255 }, { "012", 10 } }; /* Safe envoronment. */ oldenv = getenv("ZPC_TEST_AES_KEY_FLAGS"); for (i = 0; i < NMEMB(kat); i++) { rc = setenv("ZPC_TEST_AES_KEY_FLAGS", kat[i].flagsstr, 1); ASSERT_EQ(rc, 0); flags = testlib_env_aes_key_flags(); EXPECT_EQ(flags, kat[i].flagsint); rc = unsetenv("ZPC_TEST_AES_KEY_FLAGS"); ASSERT_EQ(rc, 0); } if (oldenv != NULL) { /* Restore environment. */ rc = setenv("ZPC_TEST_AES_KEY_FLAGS", oldenv, 1); ASSERT_EQ(rc, 0); } } TEST(testlib, hexstr2buf) { const u8 buf1[] = {0xde, 0xad, 0xbe, 0xef}; const u8 buf2[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xaA, 0xbB, 0xcC, 0xdD, 0xeE, 0xfF}; u8 *buf; size_t buflen; buf = testlib_hexstr2buf(NULL, &buflen); EXPECT_EQ(buflen, (size_t)0); EXPECT_EQ(buf, nullptr); buf = testlib_hexstr2buf("", &buflen); EXPECT_EQ(buflen, (size_t)0); EXPECT_EQ(buf, nullptr); free(buf); buf = testlib_hexstr2buf("0x", &buflen); EXPECT_EQ(buflen, (size_t)0); EXPECT_EQ(buf, nullptr); free(buf); buf = testlib_hexstr2buf("0x 1", &buflen); EXPECT_EQ(buflen, (size_t)0); EXPECT_EQ(buf, nullptr); free(buf); buf = testlib_hexstr2buf("0xa", &buflen); EXPECT_EQ(buflen, (size_t)0); EXPECT_EQ(buf, nullptr); free(buf); buf = testlib_hexstr2buf("A", &buflen); EXPECT_EQ(buflen, (size_t)0); EXPECT_EQ(buf, nullptr); free(buf); buf = testlib_hexstr2buf("9a", &buflen); EXPECT_EQ(buflen, (size_t)1); ASSERT_NE(buf, nullptr); EXPECT_EQ(buf[0], 0x9a); free(buf); buf = testlib_hexstr2buf("0xBc", &buflen); EXPECT_EQ(buflen, (size_t)1); ASSERT_NE(buf, nullptr); EXPECT_EQ(buf[0], 0xBc); free(buf); buf = testlib_hexstr2buf("crypto", NULL); EXPECT_EQ(buflen, (size_t)1); EXPECT_EQ(buf, nullptr); free(buf); buf = testlib_hexstr2buf("deadbeef", &buflen); ASSERT_NE(buf, nullptr); EXPECT_EQ(buflen, (size_t)4); EXPECT_TRUE(memcmp(buf, buf1, buflen) == 0); free(buf); buf = testlib_hexstr2buf("0x0123456789aAbBcCdDeEfF", &buflen); ASSERT_NE(buf, nullptr); EXPECT_EQ(buflen, (size_t)11); EXPECT_TRUE(memcmp(buf, buf2, buflen) == 0); free(buf); buf = testlib_hexstr2buf("0123456789aAbBcCdDeEfF", &buflen); ASSERT_NE(buf, nullptr); EXPECT_EQ(buflen, (size_t)11); EXPECT_TRUE(memcmp(buf, buf2, buflen) == 0); free(buf); } TEST(testlib, buf2hexstr) { const u8 buf1[] = {0xde, 0xad, 0xbe, 0xef}; const u8 buf2[] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xaA, 0xbB, 0xcC, 0xdD, 0xeE, 0xfF}; char *hexstr; hexstr = testlib_buf2hexstr(NULL, 0); EXPECT_EQ(hexstr, nullptr); free(hexstr); hexstr = testlib_buf2hexstr(NULL, 1); EXPECT_EQ(hexstr, nullptr); free(hexstr); hexstr = testlib_buf2hexstr(buf1, 0); EXPECT_EQ(hexstr, nullptr); free(hexstr); hexstr = testlib_buf2hexstr(buf1, SIZE_MAX / 2); EXPECT_EQ(hexstr, nullptr); free(hexstr); hexstr = testlib_buf2hexstr(buf1, sizeof(buf1)); ASSERT_NE(hexstr, nullptr); EXPECT_TRUE(strcmp(hexstr, "deadbeef") == 0); free(hexstr); hexstr = testlib_buf2hexstr(buf2, sizeof(buf2)); ASSERT_NE(hexstr, nullptr); EXPECT_TRUE(strcmp(hexstr, "0123456789aabbccddeeff") == 0); free(hexstr); } libzpc-1.0.0/test/testlib.cc000066400000000000000000000101301413160260300157160ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #include "testlib.h" #include "zpc/aes_key.h" #include #include #include #include #define ENV_AES_KEY_MKVP "ZPC_TEST_AES_KEY_MKVP" #define ENV_AES_KEY_APQNS "ZPC_TEST_AES_KEY_APQNS" #define ENV_AES_KEY_SIZE "ZPC_TEST_AES_KEY_SIZE" #define ENV_AES_KEY_TYPE "ZPC_TEST_AES_KEY_TYPE" #define ENV_AES_KEY_FLAGS "ZPC_TEST_AES_KEY_FLAGS" static int ishexdigit(const char); static unsigned char hexdigit2byte(char); static char byte2hexdigit(unsigned char); const char * testlib_env_aes_key_mkvp(void) { char *env; env = getenv(ENV_AES_KEY_MKVP); return env; } int testlib_env_aes_key_apqns(const char *apqns[257]) { char *env, *tok; int i; env = getenv(ENV_AES_KEY_APQNS); if (env == NULL) return -1; i = 0; tok = strtok(env, " \t\n,"); while (tok && i < 256) { apqns[i] = tok; tok = strtok(NULL, " \t\n,"); i++; } apqns[i] = NULL; return 0; } int testlib_env_aes_key_size(void) { int size = -1; /* Invalid key-size. */ long sizelong = LONG_MIN; char *env = NULL, *endptr = NULL; env = getenv(ENV_AES_KEY_SIZE); if (env == NULL || env[0] == '\0') goto ret; sizelong = strtol(env, &endptr, 0); if (*endptr != '\0' || sizelong < INT_MIN || sizelong > INT_MAX) goto ret; size = (int)sizelong; ret: return size; } int testlib_env_aes_key_type(void) { int type = -1; /* Invalid key-type. */ char *env = NULL; env = getenv(ENV_AES_KEY_TYPE); if (env == NULL) goto ret; if (strcmp(env, "ZPC_AES_KEY_TYPE_CCA_DATA") == 0) type = ZPC_AES_KEY_TYPE_CCA_DATA; else if (strcmp(env, "ZPC_AES_KEY_TYPE_CCA_CIPHER") == 0) type = ZPC_AES_KEY_TYPE_CCA_CIPHER; else if (strcmp(env, "ZPC_AES_KEY_TYPE_EP11") == 0) type = ZPC_AES_KEY_TYPE_EP11; ret: return type; } unsigned int testlib_env_aes_key_flags(void) { int flags = 0; /* Default flags. */ long flagslong = LONG_MIN; char *env = NULL, *endptr = NULL; env = getenv(ENV_AES_KEY_FLAGS); if (env == NULL || env[0] == '\0') goto ret; flagslong = strtol(env, &endptr, 0); if (*endptr != '\0' || flagslong < 0 || flagslong > UINT_MAX) goto ret; flags = (unsigned int)flagslong; ret: return flags; } unsigned char * testlib_hexstr2buf(const char *hexstr, size_t *buflen) { unsigned char *buf = NULL; const char *ptr; size_t len, i; int err = 1; if (buflen != NULL) *buflen = 0; ptr = hexstr; if (ptr == NULL) goto ret; /* Skip possible leading '0x'. */ if (strlen(ptr) > 2 && ptr[0] == '0' && ptr[1] == 'x') ptr += 2; len = strlen(ptr); if (len % 2 != 0 || len == 0) goto ret; buf = (unsigned char *)calloc(1, len / 2); if (buf == NULL) goto ret; for (i = 0; i + 1 < len; i += 2) { if (!ishexdigit(ptr[i]) || !ishexdigit(ptr[i + 1])) goto ret; buf[i / 2] = hexdigit2byte(ptr[i]) << 4; buf[i / 2] += hexdigit2byte(ptr[i + 1]); if (buflen != NULL) (*buflen)++; } err = 0; ret: if (err) { free(buf); buf = NULL; } return buf; } char * testlib_buf2hexstr(const unsigned char *buf, size_t buflen) { char *hexstr = NULL; int err = 1; size_t i; if (buf == NULL || buflen == 0) goto ret; if (buflen * 2 + 1 < buflen) goto ret; hexstr = (char *)calloc(1, buflen * 2 + 1); if (hexstr == NULL) goto ret; for (i = 0; i < buflen; i++) { hexstr[2 * i] = byte2hexdigit(buf[i] >> 4); hexstr[2 * i + 1] = byte2hexdigit(buf[i] & 0xf); } hexstr[2 * i] = '\0'; err = 0; ret: if (err) { free(hexstr); buf = 0; } return hexstr; } static int ishexdigit(const char d) { return ((d >= '0' && d <= '9') || (d >= 'A' && d <= 'F') || (d >= 'a' && d <= 'f')); } static unsigned char hexdigit2byte(char d) { const char noff = '0' - 0; const char uoff = 'A' - 10; const char loff = 'a' - 10; return (d >= 'a' ? d - loff : (d >= 'A' ? d - uoff : d - noff)); } static char byte2hexdigit(unsigned char b) { const char noff = '0' - 0; const char loff = 'a' - 10; assert((b & 0xf0) == 0); return (b >= 10 ? b + loff : b + noff); } libzpc-1.0.0/test/testlib.h000066400000000000000000000072031413160260300155670ustar00rootroot00000000000000/* * Copyright IBM Corp. 2021 * * libzpc is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. */ #ifndef TESTLIB_H # define TESTLIB_H # include "gtest/gtest.h" # ifdef __cplusplus /* *INDENT-OFF* */ extern "C" { /* *INDENT-ON* */ # endif # include # define UNUSED(x) (void)(x) # define NMEMB(x) (sizeof(x) / sizeof(x[0])) /* * GTEST_SKIP_ assumes the caller to be the test function that is to * be skipped. So this one has to be implemented as a macro. */ # define TESTLIB_ENV_AES_KEY_CHECK() \ do { \ const char *apqns[257]; \ const char *mkvp; \ int size, type, rc; \ \ size = testlib_env_aes_key_size(); \ switch (size) { \ case 128: /* fall-through */ \ case 192: /* fall-through */ \ case 256: /* fall-through */ \ break; \ case -1: \ GTEST_SKIP_("ZPC_TEST_AES_KEY_SIZE environment variable not set."); \ break; \ default: \ GTEST_SKIP_("ZPC_TEST_AES_KEY_SIZE environment variable set to invalid key-size."); \ break; \ } \ \ type = testlib_env_aes_key_type(); \ if (type == -1) \ GTEST_SKIP_("ZPC_TEST_AES_KEY_TYPE environment variable not set."); \ \ mkvp = testlib_env_aes_key_mkvp(); \ rc = testlib_env_aes_key_apqns(apqns); \ if (rc == 0 && mkvp != NULL) \ GTEST_SKIP_("Both ZPC_TEST_AES_KEY_MKVP and ZPC_TEST_AES_KEY_APQNS environment variables set."); \ if (rc != 0 && mkvp == NULL) \ GTEST_SKIP_("ZPC_TEST_AES_KEY_MKVP and ZPC_TEST_AES_KEY_APQNS environment variables unset."); \ } while (0) typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned long long u64; const char *testlib_env_aes_key_mkvp(void); int testlib_env_aes_key_apqns(const char *[257]); void testlib_env_aes_key_check(void); int testlib_env_aes_key_size(void); int testlib_env_aes_key_type(void); unsigned int testlib_env_aes_key_flags(void); unsigned char *testlib_hexstr2buf(const char *, size_t *); char *testlib_buf2hexstr(const unsigned char *, size_t); # ifdef __cplusplus /* *INDENT-OFF* */ } /* *INDENT-ON* */ # endif #endif