diff --git a/.gitignore b/.gitignore index 378eac2..c1ec017 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +generated-docs diff --git a/CHANGELOG.rst b/CHANGELOG.rst index dca1cad..8f237a6 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,8 +1,18 @@ ========= Changelog ========= +0.3.3 - July 2025 +~~~~~~~~~~~~~~~~~~~~~~ +* The register secret operation usage mask fixed, works Fortanix server +* The get secret operation key format type fixed, works Fortanix server + +0.3.2: -- May 2025 +~~~~~~~~~~~~~~~~~~~~~ +0.3.1: +0.3.0: -.. _v0.3.0: +* locate_secrets_* operations added to kmippp +* Fix of key registration with HashiCorp Vault 0.3.0 - March 19, 2025 ~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/CMakeLists.txt b/CMakeLists.txt index 6d85c2c..24e14fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.5.0) +cmake_minimum_required(VERSION 3.10.0) if (POLICY CMP0048) cmake_policy(SET CMP0048 NEW) @@ -6,8 +6,28 @@ endif(POLICY CMP0048) project(kmip C CXX) +enable_testing() + set(KMIP_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}") add_subdirectory(libkmip/src) add_subdirectory(kmippp) +add_subdirectory(kmipclient) + +find_package(Doxygen REQUIRED) + +if(DOXYGEN_FOUND) + configure_file(Doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile COPYONLY) + + add_custom_target(doc + COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "Generating API documentation with Doxygen" + VERBATIM + ) + # Make the 'doc' target depend on your build targets if necessary + # add_dependencies(doc your_library your_executable) +else() + message(STATUS "Doxygen not found, skipping documentation generation.") +endif() diff --git a/Doxyfile b/Doxyfile new file mode 100644 index 0000000..ab18de1 --- /dev/null +++ b/Doxyfile @@ -0,0 +1,36 @@ +# Project information +PROJECT_NAME = libkmip +PROJECT_NUMBER = 0.4.0 +OUTPUT_DIRECTORY = generated-docs + +# Input settings +INPUT = . # Scan the current directory for source files +RECURSIVE = YES + +# Output settings +GENERATE_LATEX = NO +GENERATE_MAN = NO +GENERATE_RTF = NO +GENERATE_XML = NO +GENERATE_HTMLHELP = YES + +# UML related settings +UML_LOOK = YES +HAVE_DOT = YES +DOT_PATH = /usr/bin/dot # Adjust this path to where your 'dot' executable is located +PLANTUML_JAR_PATH = /usr/share/java/plantuml.jar +PLANTUML_PREPROC = NO +PLANTUML_INCLUDE_PATH = +PLANTUML_CONFIG_FILE = +# Enable class diagram generation +CLASS_DIAGRAMS = YES +COLLABORATION_GRAPH = YES +UML_LIMIT_NUM_FIELDS = 50 +TEMPLATE_RELATIONS = YES +MAX_DOT_GRAPH_DEPTH = 0 +MAX_DOT_GRAPH_NODES = 0 +HIDE_UNDOC_MEMBERS = NO +HIDE_VIRTUAL_FUNCTIONS = NO +SHOW_INCLUDE_FILES = YES +SHOW_USED_FILES = YES +SHOW_FILES = YES diff --git a/kmipclient/CHANGELOG.md b/kmipclient/CHANGELOG.md new file mode 100644 index 0000000..bf71e0b --- /dev/null +++ b/kmipclient/CHANGELOG.md @@ -0,0 +1,10 @@ +Dec, 2025 Version 0.1.1 + + Interface optimization + Test suite added + Bugs fixed + +Apr, 2025 Version 0.1.0 + + Initial implementation of all functionality available in "kmippp" + diff --git a/kmipclient/CMakeLists.txt b/kmipclient/CMakeLists.txt new file mode 100644 index 0000000..11e033a --- /dev/null +++ b/kmipclient/CMakeLists.txt @@ -0,0 +1,126 @@ +cmake_minimum_required(VERSION 3.16) +project(kmipclient) + +#Have to put these 2 lines here to compile + +set(CMAKE_CXX_STANDARD 20) +include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include) + +add_library( + kmipclient + STATIC + include/KmipClient.hpp + src/KmipClient.cpp + include/NetClient.hpp + src/NetClientOpenSSL.cpp + include/NetClientOpenSSL.hpp + include/kmip_data_types.hpp + src/RequestFactory.cpp + src/RequestFactory.hpp + src/KmipCtx.hpp + src/KmipRequest.hpp + src/IOUtils.cpp + src/IOUtils.hpp + include/Kmip.hpp + src/ResponseResult.cpp + src/ResponseResult.hpp + include/kmip_exceptions.hpp + src/AttributesFactory.cpp + src/AttributesFactory.hpp + src/KeyFactory.cpp + src/KeyFactory.hpp + src/Key.cpp + include/Key.hpp + src/StringUtils.cpp + src/StringUtils.hpp + include/Logger.hpp +) + +target_include_directories( + kmipclient PUBLIC + $ + $ +) + +target_link_libraries(kmipclient kmip) + +set_property(TARGET kmipclient PROPERTY POSITION_INDEPENDENT_CODE ON) + + +target_compile_features(kmipclient INTERFACE cxx_std_20) + +set_target_properties(kmipclient PROPERTIES + CXX_STANDARD_REQUIRED YES + CXX_EXTENSIONS NO +) + +option(WITH_ASAN "Enable Address Sanitizer" OFF) +if(WITH_ASAN) + target_compile_options(kmipclient INTERFACE "-fsanitize=address") + target_link_options(kmipclient INTERFACE "-fsanitize=address") +endif() + +export(TARGETS kmip kmipclient FILE "kmipclient.cmake") + +install( + TARGETS kmipclient + EXPORT kmipclient + DESTINATION cmake + ARCHIVE DESTINATION lib + PUBLIC_HEADER DESTINATION include/ + LIBRARY DESTINATION lib) + +macro(add_example name) + add_executable(example_${name} examples/example_${name}.cpp) + target_link_libraries(example_${name} PRIVATE kmipclient) +endmacro() + +add_example(create_aes) +add_example(register_secret) +add_example(activate) +add_example(get) +add_example(get_name) +add_example(get_secret) +add_example(revoke) +add_example(destroy) +add_example(register_key) +add_example(locate) +add_example(locate_by_group) +add_example(get_all_ids) +add_example(get_attributes) + + +# Google Test integration +option(BUILD_TESTS "Build the tests" OFF) + +if(BUILD_TESTS) + if (NOT (TARGET gtest OR TARGET gmock)) + include(FetchContent) + FetchContent_Declare( + googletest + GIT_REPOSITORY https://github.com/google/googletest.git + GIT_TAG v1.14.0 + ) + + # For Windows: Prevent overriding the parent project's compiler/linker settings + set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + FetchContent_MakeAvailable(googletest) + endif () + + enable_testing() + + add_executable( + kmipclient_test + tests/KmipClientIntegrationTest.cpp + ) + + target_link_libraries( + kmipclient_test + PRIVATE + GTest::gtest_main + kmipclient + ) + + include(GoogleTest) + gtest_discover_tests(kmipclient_test) +endif() diff --git a/kmipclient/README.md b/kmipclient/README.md new file mode 100644 index 0000000..df4e274 --- /dev/null +++ b/kmipclient/README.md @@ -0,0 +1,187 @@ +The "kmipclient" library +-- +KMIP client is the C++ library that allows simple access to the KMIP servers using the KMIP protocol. + +The "kmipclient" library wraps up the low-level libkmip (kmip.h, kmip.c) into C++ code. +The purpose of such wrap-up is to: + +## Design goals. + +1. Provide easy to use and hard to misuse interface with forced error processing. +2. Hide low-level details. +3. Minimize manual memory management +4. Make the library easy to extend +5. Exclude mid-level (kmip_bio.c), use the low-level (kmip.c) only +6. Simple to replace network communication level +7. Testability + +## External dependencies + +No extra external dependencies should be used, except existing OpenSSL dependency. +KmipClient itself does not depend on any library except "kmip". The network communication level is injected +into KmipClient instance as implementation of the NetClient interface. The library has ready to use +OpenSSL BIO based implementation called NetClientOpenSSL. User of the library can use any other library to +implement the communication level. + +## High level design + +The top interface wraps network communication level (based on OpenSSL) and the KMIP protocol encoding level. +It is implemented as header-only class in the file “Kmip.hpp” and can be used similar to the old C++ wrapper +(kmippp.h). Actual high level interface consists of two headers: NetClient.hpp. and KmipClient.hpp. + +The first interface is just a contract to wrap low-level network communications similar to well-known +interfaces (socket, OpenSSL bio and others). It contains 4 methods only: connect(), close(), send() +and receive(). This interface also has an implementation, declared “NetClientOpenSSL.hpp”. +It is based on OpenSSL BIO functions. + +The second interface is actual KMIP protocol implementation. It requires a NetClient implementation +as a dependency injection in the constructor. This interface is also similar to the existing C++ wrapper +and can be used the similar way when properly initialized with the NetClient-derived instance. + +All KMIP request creation and encoding are encapsulated in the RequestFactory class. All operations are +on stack and do not require memory management. + +All KMIP responses processing are encapsulated in ResponseFactory class. It should be operated on stack +to keep data in place. Copy and move operations are disabled. + +By the protocol, parsed response contains one or more response batch items. To process these items, +ResponseFactory class is used. It’s purpose is to extract values from the response batch item. V +alues are keys, secrets, attributes, etc. This class does not have a state and consists of static methods. + +All operation in the low-level KMIP library are based on context structure KMIP. This structure is +encapsulated in KmipCtx class along with operations on buffers, errors, etc. This class, once created, +is passed by the reference to other classes of the “kmipclient” library. Copy and move operations are +disabled for this class also. Usually, the instance of this class is created on stack in the high-level +methods and does not require memory management. + +The high-level interface usage example: + +```C++ + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + + try + { + std::string id = argv[6]; + auto key = client.op_get_key (id); + std::cout << "Key: 0x"; + print_hex (key.value ()); + std::cout << "State: " << key.attribute_value (KMIP_ATTR_NAME_STATE); + } + catch (const std::exception &e) + { + std::cerr << "Can not get key with id:" << argv[6] << " Cause: " << e.what () << std::endl; + return 1; + }; +``` +As can be seen from the code above, the NetClientOpenSSL class instance is injected as dependency +inversion into the KmipClient class instance. This approach allows to use any net connection with KmipClient. +It is enough to derive the class from NetClient class and wrap 4 calls. + +To understand, how to extend functionality, below is example of request creation: + +```C++ +void +RequestFactory::create_get_rq (KmipCtx &ctx, const id_t &id) +{ + KmipRequest rq (ctx); + TextString uuid = {}; + uuid.size = id.size (); + uuid.value = const_cast(id.c_str ()); + + GetRequestPayload grp {}; + grp.unique_identifier = &uuid; + + RequestBatchItem rbi {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_GET; + rbi.request_payload = &grp; + rq.set_batch_item (&rbi); + rq.encode (); +} +``` +In the example above we use low-level primitives from “kmip.h” to create the RequestBatchItem and +then we add it to the internal member of “KmipRequest” class, which performs appropriate +request encoding in to the KMIP context. + +Below is an example of the response processing: + +```C++ +ve::expected +ResponseResultFactory::get_key (ResponseBatchItem *rbi) +{ + auto *pld = static_cast (rbi->response_payload); + switch (pld->object_type) + { + //name known key to KeyFactory types + case KMIP_OBJTYPE_SYMMETRIC_KEY: + KMIP_OBJTYPE_PUBLIC_KEY: + KMIP_OBJTYPE_PRIVATE_KEY: + KMIP_OBJTYPE_CERTIFICATE: + { + return KeyFactory::parse_response(pld); + }; + default: + return Error(-1,"Invalid response object type."); + } +} + +``` +And here is an example of top-level function implementation + +```C++ +Key +KmipClient::op_get_key (const id_t &id) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_get_rq (ctx, id); + io->do_exchange (ctx); + return rf.get_key (0); +} +``` +As can be seen from the source code, each KMIP low-level entity is encapsulated in some C++ class, +therefore advanced C++ memory management is utilized. Also, the design is avoiding any kind +of smart pointers (almost… sometimes we need it), using on-stack variables. Raw pointers from +the low-level code are used rarely just to pass stack-based data for more detailed processing. + +It is worth mentioning that KMIP protocol supports multiple request items ( batch items ) +in one network request. For example, it might be combination of GET and GET_ATTRRIBUTE operations +to have a key with set of it’s attributes. It is important to have key state attribute, +because a key could be outdated, deactivated or marked as compromised. + +At the moment, the interface is prepared for multiple request items in one request. But, it is not +implemented in the library yet, because our plans are to remove old code (kmip.c) completelly and replace +it with safe and clean C++ implementation. Actually, this is the protocol serialization/decerialization +level only, so it is not a big deal. + + +## Usage + +Please see usage examples in the "examples" directory +## Build +```bash +mkdir build +cd build +cmake .. +cmake --build . +``` +## Integration testing + +Tests are implemented using the Google Test framework. The source code is in the "tests" directory. + +To run the internal test suite, please, do the following: + +1. Export the following variables: KMIP_PORT, KMIP_CLIENT_CA, KMIP_CLIENT_KEY, KMIP_SERVER_CA. Example: +```bash + export KMIP_ADDR=127.0.0.1 + export KMIP_PORT=5696 + export KMIP_CLIENT_CA=/path/to/client_cert.pem + export KMIP_CLIENT_KEY=/path/to/client_key.pem + export KMIP_SERVER_CA=/path/to/server_cert.pem +``` + +2. Run "cmake -DBUILD_TESTS=ON .." from the build directory. +3. Run "cmake --build ." from the build directory. + + diff --git a/kmipclient/TODO.md b/kmipclient/TODO.md new file mode 100644 index 0000000..b905fd6 --- /dev/null +++ b/kmipclient/TODO.md @@ -0,0 +1,12 @@ +TODO +-- +The list of things yet to be done + +1. Re-write protocol serialization/deserialization completelly and remove the dependency on `kmip.c` +2. Multiple batch items requests and responses for cases like "register and activate", "revoke and destroy", +"get key and attributes", etc. +3. Multiple attributes getting +4. Asymmetric keys and certificates support +5. Version negotiation with the KMIP server (Default is 1.4) +6. Human-readable request and response logging + diff --git a/kmipclient/examples/example_activate.cpp b/kmipclient/examples/example_activate.cpp new file mode 100644 index 0000000..fb38260 --- /dev/null +++ b/kmipclient/examples/example_activate.cpp @@ -0,0 +1,52 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + if (argc < 7) + { + std::cerr << "Usage: example_activate " + << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + try + { + const auto opt_key = client.op_activate (argv[6]); + std::cout << "Key wih ID: " << argv[6] << " is activated." << std::endl; + return 0; + } + catch (const std::exception &e) + { + std::cerr << "Can not activate key with id:" << argv[6] << " Cause: " << e.what () << std::endl; + }; + + return -1; +} diff --git a/kmipclient/examples/example_create_aes.cpp b/kmipclient/examples/example_create_aes.cpp new file mode 100644 index 0000000..4662a1a --- /dev/null +++ b/kmipclient/examples/example_create_aes.cpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "Kmip.hpp" +#include "KmipClient.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 7) + { + std::cerr << "Usage: example_create_aes " + << std::endl; + return -1; + } + + Kmip kmip (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + try + { + auto key_id = kmip.client ().op_create_aes_key (argv[6], "TestGroup"); + std::cout << "Key ID: " << key_id << std::endl; + return 0; + } + catch (std::exception &e) + { + std::cerr << "Can not create key with name:" << argv[6] << " Cause: " << e.what () << std::endl; + } + return -1; +} diff --git a/kmipclient/examples/example_destroy.cpp b/kmipclient/examples/example_destroy.cpp new file mode 100644 index 0000000..2ac38b0 --- /dev/null +++ b/kmipclient/examples/example_destroy.cpp @@ -0,0 +1,52 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 7) + { + std::cerr << "Usage: example_destroy " + << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + try + { + const auto opt_key = client.op_destroy (argv[6]); + std::cout << "Key ID: " << argv[6] << " is destroyed." << std::endl; + } + catch (const std::exception &e) + { + std::cerr << "Can not get key with id:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + } + return 0; +} diff --git a/kmipclient/examples/example_get.cpp b/kmipclient/examples/example_get.cpp new file mode 100644 index 0000000..ebfd8ab --- /dev/null +++ b/kmipclient/examples/example_get.cpp @@ -0,0 +1,67 @@ + +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "../include/kmip_exceptions.hpp" +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +void +print_hex (const kmipclient::key_t &key) +{ + for (auto const &c : key) + { + std::cout << std::hex << static_cast (c); + } + std::cout << std::endl; +} + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + if (argc < 7) + { + std::cerr << "Usage: example_get " << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + + try + { + std::string id = argv[6]; + auto key = client.op_get_key (id); + std::cout << "Key: 0x"; + print_hex (key.value ()); + std::cout << "State: " << key.attribute_value (KMIP_ATTR_NAME_STATE); + } + catch (const std::exception &e) + { + std::cerr << "Can not get key with id:" << argv[6] << " Cause: " << e.what () << std::endl; + return 1; + }; + + return 0; +} diff --git a/kmipclient/examples/example_get_all_ids.cpp b/kmipclient/examples/example_get_all_ids.cpp new file mode 100644 index 0000000..9a8099f --- /dev/null +++ b/kmipclient/examples/example_get_all_ids.cpp @@ -0,0 +1,69 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + +This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + if (argc < 6) + { + std::cerr << "Usage: example_get_all_ids " << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + + try + { + const auto opt_ids = client.op_all (KMIP_OBJTYPE_SYMMETRIC_KEY); + std::cout << "Found IDs of symmetric keys:" << std::endl; + for (const auto &id : opt_ids) + { + std::cout << id << std::endl; + } + } + catch (const std::exception &e) + { + std::cerr << "Can not get keys." << " Cause: " << e.what () << std::endl; + }; + + try + { + const auto opt_ids_s = client.op_all (KMIP_OBJTYPE_SECRET_DATA); + std::cout << "Found IDs of secret data:" << std::endl; + for (const auto &id : opt_ids_s) + { + std::cout << id << std::endl; + } + } + catch (const std::exception &e) + { + std::cerr << "Can not get id-s. Cause: " << e.what () << std::endl; + }; + + return 0; +} diff --git a/kmipclient/examples/example_get_attributes.cpp b/kmipclient/examples/example_get_attributes.cpp new file mode 100644 index 0000000..28ca844 --- /dev/null +++ b/kmipclient/examples/example_get_attributes.cpp @@ -0,0 +1,92 @@ + +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" +#include "kmip_exceptions.hpp" + +using namespace kmipclient; + +void +print_hex (const kmipclient::key_t &key) +{ + for (auto const &c : key) + { + std::cout << std::hex << static_cast (c); + } + std::cout << std::endl; +} + +void +print_attributes (const attributes_t &attrs) +{ + for (auto const &attr : attrs) + { + std::cout << attr.first << ": " << attr.second << std::endl; + } +} + +/* This example is incomplete because of the low-level kmip.c is quite incomplete, + * and there's no sense to complete exiting ugly C code. The next version of the "KMIPClient" library + * will remove dependency on old C code and will be replaced with C++ code + * of the protocol serialization/deserialization + */ + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + if (argc < 7) + { + std::cerr << "Usage: example_get " << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + + try + { + std::string id = argv[6]; + auto key = client.op_get_key (id); + std::cout << "Key: 0x"; + print_hex (key.value ()); + auto attr_names = client.op_get_attribute_list (id); + // TODO: operation below should give 2 attributes but gives the first only. Problem is in kmip.c + // auto attr = client.op_get_attributes (id, {KMIP_ATTR_NAME_STATE, KMIP_ATTR_NAME_NAME}); + // TODO: operation below should give all available attributes but gives none + // auto attr = client.op_get_attributes (id, {}); + // at the moment we get attributes one by one, the State attribute is fetched with the key, + // and we also added the Name attribute by the separate call to the server + auto attr = client.op_get_attributes (id, { KMIP_ATTR_NAME_NAME }); + key.set_attribute (KMIP_ATTR_NAME_NAME, attr[KMIP_ATTR_NAME_NAME]); + std::cout << "Attributes: " << std::endl; + print_attributes (key.attributes ()); + } + catch (const std::exception &e) + { + std::cerr << "Can not get key with id:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + }; + + return 0; +} diff --git a/kmipclient/examples/example_get_name.cpp b/kmipclient/examples/example_get_name.cpp new file mode 100644 index 0000000..2e26f74 --- /dev/null +++ b/kmipclient/examples/example_get_name.cpp @@ -0,0 +1,66 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +void +print_attributes (const attributes_t &attrs) +{ + for (auto const &attr : attrs) + { + std::cout << attr.first << ": " << attr.second << std::endl; + } +} + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 7) + { + std::cerr << "Usage: example_get_name " + << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + try + { + // get name + auto opt_attr = client.op_get_attributes (argv[6], { KMIP_ATTR_NAME_NAME }); + // get group + opt_attr.merge (client.op_get_attributes (argv[6], { KMIP_ATTR_NAME_GROUP })); + std::cout << "ID: " << argv[6] << " Attributes:" << std::endl; + print_attributes (opt_attr); + } + catch (const std::exception &e) + { + std::cerr << "Can not get name or group for id:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + }; + + return 0; +} diff --git a/kmipclient/examples/example_get_secret.cpp b/kmipclient/examples/example_get_secret.cpp new file mode 100644 index 0000000..0653008 --- /dev/null +++ b/kmipclient/examples/example_get_secret.cpp @@ -0,0 +1,53 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 6) + { + std::cerr << "Usage: example_get_secret " + << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + try + { + auto opt_secret = client.op_get_secret (argv[6]); + std::cout << "Secret: " << opt_secret.value << std::endl; + } + catch (std::exception &e) + { + std::cerr << "Can not get key with id:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + }; + + return 0; +} diff --git a/kmipclient/examples/example_locate.cpp b/kmipclient/examples/example_locate.cpp new file mode 100644 index 0000000..6e7278b --- /dev/null +++ b/kmipclient/examples/example_locate.cpp @@ -0,0 +1,74 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 7) + { + std::cerr << "Usage: example_locate " << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + + std::cout << "Searching for name: " << argv[6] << std::endl; + try + { + const auto opt_ids = client.op_locate_by_name (argv[6], KMIP_OBJTYPE_SYMMETRIC_KEY); + + std::cout << "Found IDs of symmetric keys:" << std::endl; + for (const auto &id : opt_ids) + { + std::cout << id << std::endl; + } + } + catch (const std::exception &e) + { + std::cerr << "Can not get keys with name:" << argv[6] << " Cause: " << e.what () << std::endl; + return 1; + }; + + try + { + const auto opt_ids_s = client.op_locate_by_name (argv[6], KMIP_OBJTYPE_SECRET_DATA); + std::cout << "Found IDs of secret data:" << std::endl; + for (const auto &id : opt_ids_s) + { + std::cout << id << std::endl; + } + } + catch (const std::exception &e) + { + std::cerr << "Can not get secrets with name:" << argv[6] << " Cause: " << e.what () << std::endl; + return 1; + }; + + return 0; +} diff --git a/kmipclient/examples/example_locate_by_group.cpp b/kmipclient/examples/example_locate_by_group.cpp new file mode 100644 index 0000000..8222f68 --- /dev/null +++ b/kmipclient/examples/example_locate_by_group.cpp @@ -0,0 +1,74 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 7) + { + std::cerr << "Usage: example_locate_by_group " + << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + + std::cout << "Searching for group with name: " << argv[6] << std::endl; + try + { + const auto opt_ids = client.op_locate_by_group (argv[6], KMIP_OBJTYPE_SYMMETRIC_KEY); + std::cout << "Found IDs of symmetric keys:"; + for (const auto &id : opt_ids) + { + std::cout << id << std::endl; + } + } + catch (const std::exception &e) + { + std::cerr << "Can not get keys with group name:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + }; + + try + { + const auto opt_ids_s = client.op_locate_by_group (argv[6], KMIP_OBJTYPE_SECRET_DATA); + std::cout << "Found IDs of secret data:"; + for (const auto &id : opt_ids_s) + { + std::cout << id << std::endl; + } + } + catch (std::exception &e) + { + std::cerr << "Can not get secrets with group name:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + }; + + return 0; +} diff --git a/kmipclient/examples/example_register_key.cpp b/kmipclient/examples/example_register_key.cpp new file mode 100644 index 0000000..d0c0b89 --- /dev/null +++ b/kmipclient/examples/example_register_key.cpp @@ -0,0 +1,54 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 8) + { + std::cerr << "Usage:example_register_key " + " " + << std::endl; + return -1; + } + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + + try + { + auto k = Key::aes_from_hex (argv[7]); + const auto opt_id = client.op_register_key (argv[6], "TestGroup", k); + std::cout << "Key registered. ID: " << opt_id << std::endl; + } + catch (std::exception &e) + { + std::cerr << "Can not register key:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + }; + + return 0; +} diff --git a/kmipclient/examples/example_register_secret.cpp b/kmipclient/examples/example_register_secret.cpp new file mode 100644 index 0000000..fbe457a --- /dev/null +++ b/kmipclient/examples/example_register_secret.cpp @@ -0,0 +1,52 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "Kmip.hpp" +#include "KmipClient.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 7) + { + std::cerr << "Usage: example_register_secret " + " " + << std::endl; + return -1; + } + + Kmip kmip (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + try + { + auto id = kmip.client ().op_register_secret (argv[6], "TestGroup", argv[7], PASSWORD); + std::cout << "Secret ID: " << id << std::endl; + } + catch (std::exception &e) + { + std::cerr << "Can not register secret with name:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + } + return 0; +} diff --git a/kmipclient/examples/example_revoke.cpp b/kmipclient/examples/example_revoke.cpp new file mode 100644 index 0000000..f8d6ac2 --- /dev/null +++ b/kmipclient/examples/example_revoke.cpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include + +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" +#include "kmipclient_version.hpp" + +using namespace kmipclient; + +int +main (int argc, char **argv) +{ + std::cout << "KMIP CLIENT version: " << KMIPCLIENT_VERSION_STR << std::endl; + std::cout << "KMIP library version: " << KMIP_LIB_VERSION_STR << std::endl; + + if (argc < 7) + { + std::cerr << "Usage: example_revoke " << std::endl; + return -1; + } + + NetClientOpenSSL net_client (argv[1], argv[2], argv[3], argv[4], argv[5], 200); + KmipClient client (net_client); + try + { + const auto opt_key = client.op_revoke (argv[6], UNSPECIFIED, "Deactivate", 0L); + std::cout << "Key ID: " << argv[6] << " is deactivated." << std::endl; + } + catch (const std::exception &e) + { + std::cerr << "Can not get key with id:" << argv[6] << " Cause: " << e.what () << std::endl; + return -1; + }; + return 0; +} diff --git a/kmipclient/include/Key.hpp b/kmipclient/include/Key.hpp new file mode 100644 index 0000000..24a3bbe --- /dev/null +++ b/kmipclient/include/Key.hpp @@ -0,0 +1,137 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KEY_HPP +#define KEY_HPP +#include + +#include "kmip_data_types.hpp" + +namespace kmipclient +{ +/** Key types corresponding to KMIP Object Types */ +enum KeyType +{ + UNSET, + SYMMETRIC_KEY, + PUBLIC_KEY, + PRIVATE_KEY, + CERTIFICATE +}; + +class KeyFactory; + +/** + * Genric crypto key representation, as KMIP spec sees it. + */ +class Key +{ + friend class KeyFactory; + +public: + explicit Key (key_t value, KeyType k_type, cryptographic_algorithm algo, cryptographic_usage_mask usage_mask, + attributes_t attributes) + : key_value (std::move (value)), key_type (k_type), key_attributes (std::move (attributes)), + crypto_algorithm (algo), crypto_usage_mask (usage_mask) {}; + + Key () = default; + + [[nodiscard]] const key_t & + value () const noexcept + { + return key_value; + }; + + [[nodiscard]] const attributes_t & + attributes () const noexcept + { + return key_attributes; + }; + + [[nodiscard]] const std::string & + attribute_value (const std::string &name) const noexcept + { + return key_attributes.at (name); + }; + + void + set_attribute (const std::string &name, const std::string &value) noexcept + { + key_attributes[name] = value; + }; + + [[nodiscard]] cryptographic_usage_mask + usage_mask () const noexcept + { + return crypto_usage_mask; + } + + [[nodiscard]] cryptographic_algorithm + algorithm () const noexcept + { + return crypto_algorithm; + }; + + [[nodiscard]] size_t + size () const noexcept + { + return key_value.size (); + } + + /** + * Creates an instance from a hexadecimal string + * @param hex Hexadecimal string of key value + * @return AES key initialized + */ + static Key aes_from_hex (const std::string &hex); + /** + * Creates an instance from a base64 encoded string + * @param base64 Base64 encoded binary + * @return AES key initialized + */ + static Key aes_from_base64 (const std::string &base64); + + /** + * Creates an instance from a bytes vector + * @param val binary key value + * @return AES key initialized + */ + static Key aes_from_value (const std::vector &val); + /** + * Generate an AES key of given size (in bits). Valid sizes: 128, 192, 256. + * Uses OpenSSL RAND to generate cryptographically secure random bytes. + */ + static Key generate_aes (size_t size_bits); + /** + * Reads a PEM-formatted string, decides what type of key it has + * (X.509 certificate, public key, private key) and creates the + * Key instance from it. + * @param pem PEM-formatted string + * @return Key of a corresponding type + */ + static Key from_PEM (const std::string &pem); + +private: + key_t key_value; + KeyType key_type = UNSET; + attributes_t key_attributes; + cryptographic_algorithm crypto_algorithm = cryptographic_algorithm::KMIP_CRYPTOALG_UNSET; + cryptographic_usage_mask crypto_usage_mask = cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET; +}; +} + +#endif // KEY_HPP diff --git a/kmipclient/include/Kmip.hpp b/kmipclient/include/Kmip.hpp new file mode 100644 index 0000000..d3d27e1 --- /dev/null +++ b/kmipclient/include/Kmip.hpp @@ -0,0 +1,63 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIP_HPP +#define KMIP_HPP +#include "KmipClient.hpp" +#include "NetClientOpenSSL.hpp" + +namespace kmipclient +{ +/** + * Simplified interface to the KmipClient, with network client initialization + */ +class Kmip +{ +public: + /** Constructor creates instances of the OpenSSL-based network client and a KMIP protocol handling client. + * After successful initialization, use the client() method to access KMIP operations. + * Constructor possibly throws ErrorException from the NetClient! + */ + Kmip (const char *host, const char *port, const char *clientCertificateFn, const char *clientKeyFn, + const char *serverCaCertFn, int timeout_ms) + : m_net_client (host, port, clientCertificateFn, clientKeyFn, serverCaCertFn, timeout_ms), m_client (m_net_client) + { + m_net_client.connect (); + }; + + /** + * Gets reference to the inited instance of KmipClient, which has all KMIP operations. + * @return the reference to the instance of KmipClient + */ + KmipClient & + client () + { + return m_client; + }; + +private: + /** + * Instance of the NetClient using OpenSSL BIO + */ + NetClientOpenSSL m_net_client; + /** + * KMIP protocol client, initialized with m_net_client in the constructor + */ + KmipClient m_client; +}; +} +#endif // KMIP_HPP diff --git a/kmipclient/include/KmipClient.hpp b/kmipclient/include/KmipClient.hpp new file mode 100644 index 0000000..b1db9ef --- /dev/null +++ b/kmipclient/include/KmipClient.hpp @@ -0,0 +1,172 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#ifndef KMIP_CLIENT_HPP +#define KMIP_CLIENT_HPP + +#include + +#include "Key.hpp" +#include "Logger.hpp" +#include "NetClient.hpp" +#include "kmip_data_types.hpp" + +namespace kmipclient +{ + +constexpr size_t MAX_BATCHES_IN_SEARCH = 16; +constexpr size_t MAX_ITEMS_IN_BATCH = 1024; + +class IOUtils; +/** + * A client that communicates with a KMIP-compliant server to perform cryptographic operations + * such as key management, secret management, and cryptographic operations. + */ +class KmipClient +{ +public: + /** + * Creates instance of KmipClient without logger + * @param net_client pre-initialized instance of NetClient interface + */ + explicit KmipClient (NetClient &net_client); + /** + * Creates instance of KmipClient with logger + * @param net_client pre-initialized instance of NetClient interface + * @param log initialized instance of Logger interface + */ + explicit KmipClient (NetClient &net_client, const std::shared_ptr &log); + ~KmipClient (); + // no copy, no move + KmipClient (const KmipClient &) = delete; + KmipClient &operator= (const KmipClient &) = delete; + KmipClient (KmipClient &&) = delete; + KmipClient &operator= (KmipClient &&) = delete; + + /** + * KMIP register operation, stores a proposed key on the server + * @param name The "Name" attribute of the key + * @param group The group name for the key + * @param k The key to register + * @return ID of the key if success or throws ErrorException + */ + [[nodiscard]] id_t op_register_key (const name_t &name, const name_t &group, const Key &k) const; + + /** + * + * @param name The "Name" attribute of the secret + * @param group The group name for the secret + * @param secret The secret to register + * @param secret_type Type of the secret, @see + * @return ID of the key if success or throws ErrorException + */ + [[nodiscard]] id_t op_register_secret (const name_t &name, const name_t &group, std::string_view secret, + enum secret_data_type secret_type) const; + + /** KMIP::create operation, generates a new AES-256 symmetric key on the server + * @param name name attribute of the key + * @param group group attribute of the key + * @return ID of the created key or throws ErrorException + */ + [[nodiscard]] id_t op_create_aes_key (const name_t &name, const name_t &group) const; + + /** + * Gets key by ID + * @param id id of the Key + * @return The Key or throws ErrorException + */ + [[nodiscard]] Key op_get_key (const id_t &id) const; + + /** + * Gets secret by the ID + * @param id ID of the secret + * @return The secret or throws ErrorException + */ + [[nodiscard]] Secret op_get_secret (const id_t &id) const; + + /** + * Changes key/secret state from pre-active to active. + * @param id ID of the entity + * @return ID of the entity or throws ErrorException + */ + [[nodiscard]] id_t op_activate (const id_t &id) const; + + /** KMIP::get_attributes operation, retrieve the names of a symmetric key by id + * @paran id ID of the entity + * @return value of the attribute or throws ErrorException + */ + [[nodiscard]] names_t op_get_attribute_list (const id_t &id) const; + + /** KMIP::get_attribute operation, retrieve the attribute of an entity with id by attribute names name + * @param id ID of the entity + * @param attr_names names of the attribute in a vector, e.g. "Name", "State", "Object Group" + * @return value of the attribute or throws ErrorException + */ + [[nodiscard]] attributes_t op_get_attributes (const id_t &id, const std::vector &attr_names) const; + + /** KMIP::locate operation, retrieve symmetric keys by name + * Note: HasiCorp Vault does not allow name duplication + * @param name name of the entity + * @param o_type type of the entity to retrieve + * @return In general case, one ID. Some KMIP servers allow multiple IDs with the same name, so there will be multiple + * IDs. If there are no entities with such a name, an empty vector is returned. + */ + [[nodiscard]] ids_t op_locate_by_name (const name_t &name, enum object_type o_type) const; + + /** + * Gets IDs of entities by the group name + * @param group group name + * @param o_type type of the entity to retrieve + * @param max_ids maximum number of IDs to retrieve, default is MAX_BATCHES_IN_SEARCH * MAX_ITEMS_IN_BATCH + * @return vector of key IDs + */ + [[nodiscard]] ids_t op_locate_by_group (const name_t &group, enum object_type o_type, size_t max_ids = MAX_BATCHES_IN_SEARCH * MAX_ITEMS_IN_BATCH) const; + + /** + * Revokes/deactivates a key or another entity + * @param id ID of the entity + * @param reason the reason to revoke + * @param message Message of revocation to be saved in the server side + * @param occurrence_time time of the incident, 0 for the key deactivation + * @return ID of the empty string on error + */ + [[nodiscard]] id_t op_revoke (const id_t &id, enum revocation_reason_type reason, const name_t &message, + time_t occurrence_time) const; + /** + * Destroys an entity by ID + * NOTE: Entity should be revoked/deactivated + * @param id ID of the entity + * @return ID of the entity or empty string on error + */ + [[nodiscard]] id_t op_destroy (const id_t &id) const; + + /** + * KMIP::locate operation, retrieve all symmetric keys + * note: name can be empty, and will retrieve all keys + * @param o_type type of the entity to fetch + * @param max_ids maximum number of IDs to retrieve, default is MAX_BATCHES_IN_SEARCH * MAX_ITEMS_IN_BATCH + * @return vector of IDs of entities + */ + [[nodiscard]] ids_t op_all (enum object_type o_type, size_t max_ids = MAX_BATCHES_IN_SEARCH * MAX_ITEMS_IN_BATCH ) const; + +private: + NetClient &net_client; + std::shared_ptr logger = nullptr; + std::unique_ptr io; +}; + +} +#endif // KMIP_CLIENT_HPP diff --git a/kmipclient/include/Logger.hpp b/kmipclient/include/Logger.hpp new file mode 100644 index 0000000..39fa0e9 --- /dev/null +++ b/kmipclient/include/Logger.hpp @@ -0,0 +1,49 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIP_LOGGER_HPP +#define KMIP_LOGGER_HPP + +#include + +namespace kmipclient +{ +enum LogLevel +{ + TRACE = 0, + DEBUG, + INFO, + WARNING, + ERROR, + SEVERE +}; +/** + * Interface for logger + */ +class Logger +{ +public: + Logger () = default; + virtual ~Logger () = default; + Logger (const Logger &other) = delete; + Logger &operator= (const Logger &other) = delete; + Logger (Logger &&other) = delete; + Logger &operator= (Logger &&other) = delete; + virtual void log (LogLevel level, std::string_view msg) = 0; +}; +} +#endif // KMIP_LOGGER_HPP diff --git a/kmipclient/include/NetClient.hpp b/kmipclient/include/NetClient.hpp new file mode 100644 index 0000000..c518912 --- /dev/null +++ b/kmipclient/include/NetClient.hpp @@ -0,0 +1,101 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIP_NET_CLIENT_HPP +#define KMIP_NET_CLIENT_HPP + +#include + +namespace kmipclient +{ +/** + * Interface for the SSL network communication level + */ +class NetClient +{ +public: + /** + * Constructor for the KMIP SSL network level + * @param host KMIP server host + * @param port KMIP server port + * @param clientCertificateFn File path for a client X.509 certificate in PEM format + * @param clientKeyFn File path for a corresponding client private key in PEM format + * @param serverCaCertFn File path for the server cert. Also, may work with the CA certificate that signed server cert + * @param timeout_ms connection timeout in milliseconds + */ + NetClient (const std::string host, const std::string port, std::string clientCertificateFn, const std::string clientKeyFn, + const std::string serverCaCertFn, int timeout_ms) noexcept : m_host (host), + m_port (port), + m_clientCertificateFn (clientCertificateFn), + m_clientKeyFn (clientKeyFn), + m_serverCaCertificateFn (serverCaCertFn), + m_timeout_ms (timeout_ms) {}; + + virtual ~NetClient () = default; + // no copy, no move + NetClient (const NetClient &) = delete; + virtual NetClient &operator= (const NetClient &) = delete; + NetClient (NetClient &&) = delete; + virtual NetClient &operator= (NetClient &&) = delete; + /** + * Performs SSL connection to the server + * @return 0 in case of success, negative value in case of error + */ + + virtual bool connect () = 0; + /** + * Closes SSL connection to the server, returns true if connection successful + */ + virtual void close () = 0; + + /** + * Checks if the network client is already connected to the server + * @return true if the connection is established, false otherwise + */ + [[nodiscard]] bool + is_connected () const + { + return m_isConnected; + } + /** + * Sends dlen bytes from the buffer in *data + * @param data data buffer + * @param dlen number of bytes to send + * @return In success, these calls return the number of bytes sent. On error, -1 is returned + */ + virtual int send (const void *data, int dlen) = 0; + + /** + * Receives dlen bytes into the pre-allocated buffer *data + * @param data buffer for received data + * @param dlen number of bytes to receive + * @return the number of bytes received, or -1 if an error occurred + */ + virtual int recv (void *data, int dlen) = 0; + +protected: + std::string m_host; + std::string m_port; + std::string m_clientCertificateFn; + std::string m_clientKeyFn; + std::string m_serverCertFn; + std::string m_serverCaCertificateFn; + int m_timeout_ms; + bool m_isConnected = false; +}; +} +#endif // KMIP_NET_CLIENT_HPP diff --git a/kmipclient/include/NetClientOpenSSL.hpp b/kmipclient/include/NetClientOpenSSL.hpp new file mode 100644 index 0000000..1886916 --- /dev/null +++ b/kmipclient/include/NetClientOpenSSL.hpp @@ -0,0 +1,58 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIPNETCLILENTOPENSSL_HPP +#define KMIPNETCLILENTOPENSSL_HPP + +#include "NetClient.hpp" + +extern "C" +{ // we do not want to expose SSL stuff to this class users + typedef struct ssl_ctx_st SSL_CTX; + typedef struct bio_st BIO; +} + +namespace kmipclient +{ +/** + * OpenSSL's BIO-based implementation of the NetClient interface + */ +class NetClientOpenSSL : public NetClient +{ +public: + NetClientOpenSSL (std::string host, std::string port, std::string clientCertificateFn, std::string clientKeyFn, + std::string serverCaCertFn, int timeout_ms); + ~NetClientOpenSSL () override; + // no copy, no move + NetClientOpenSSL (const NetClient &) = delete; + NetClientOpenSSL &operator= (const NetClient &) override = delete; + NetClientOpenSSL (NetClient &&) = delete; + NetClientOpenSSL &operator= (NetClient &&) override = delete; + + bool connect () override; + void close () override; + int send (const void *data, int dlen) override; + int recv (void *data, int dlen) override; + +private: + SSL_CTX *ctx_ = nullptr; + BIO *bio_ = nullptr; + bool check_connected (); +}; +} + +#endif // KMIPNETCLILENTOPENSSL_HPP diff --git a/kmipclient/include/kmip_data_types.hpp b/kmipclient/include/kmip_data_types.hpp new file mode 100644 index 0000000..bfe072c --- /dev/null +++ b/kmipclient/include/kmip_data_types.hpp @@ -0,0 +1,81 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DATA_TYPES_HPP +#define DATA_TYPES_HPP + +#include +#include +#include +#include + +#include "kmip_enums.h" + +namespace kmipclient +{ +// we use protocol/specification version 1.4 as default +#define KMIP_PROTOCOL_VERSION_DEFAULT KMIP_1_4 + +// known attributes so far +static const std::string KMIP_ATTR_NAME_NAME = "Name"; +static const std::string KMIP_ATTR_NAME_GROUP = "Object Group"; +static const std::string KMIP_ATTR_NAME_STATE = "State"; +static const std::string KMIP_ATTR_NAME_UNIQUE_IDENTIFIER = "UniqueID"; + +using key_t = std::vector; +using bin_data_t = std::vector; +using id_t = std::string; +using ids_t = std::vector; +using name_t = std::string; +using names_t = std::vector; +using secret_t = std::string; +using attributes_t = std::unordered_map; + +inline std::ostream & +operator<< (std::ostream &out, const state value) +{ + const char *str; + switch (value) + { +#define PROCESS_VAL(p) \ + case (p): \ + str = #p; \ + break; + PROCESS_VAL (KMIP_STATE_PRE_ACTIVE); + PROCESS_VAL (KMIP_STATE_ACTIVE); + PROCESS_VAL (KMIP_STATE_DEACTIVATED); + PROCESS_VAL (KMIP_STATE_COMPROMISED); + PROCESS_VAL (KMIP_STATE_DESTROYED); + PROCESS_VAL (KMIP_STATE_DESTROYED_COMPROMISED); +#undef PROCESS_VAL + default: + str = "UNKNOWN_KMIP_STATE"; + break; // Handle unknown values + } + return out << str; +} + +class Secret +{ +public: + secret_t value; + enum state state = KMIP_STATE_PRE_ACTIVE; + enum secret_data_type secret_type = PASSWORD; +}; + +} +#endif // DATA_TYPES_HPP diff --git a/kmipclient/include/kmip_exceptions.hpp b/kmipclient/include/kmip_exceptions.hpp new file mode 100644 index 0000000..6d9233d --- /dev/null +++ b/kmipclient/include/kmip_exceptions.hpp @@ -0,0 +1,49 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIP_EXCEPTIONS_HPP +#define KMIP_EXCEPTIONS_HPP + +#include +#include + +namespace kmipclient +{ + +class ErrorException : public std::exception +{ +public: + explicit ErrorException (int code, std::string msg) : message (std::move (msg)), kmip_code(code) { }; + explicit ErrorException (std::string msg) : message (std::move (msg)), kmip_code(-1) { }; + [[nodiscard]] const char * + what () const noexcept override + { + return message.c_str (); + }; + [[nodiscard]] int + code () const + { + return kmip_code; + }; + +private: + std::string message; + int kmip_code; +}; + +} +#endif // KMIP_EXCEPTIONS_HPP diff --git a/kmipclient/include/kmipclient_version.hpp b/kmipclient/include/kmipclient_version.hpp new file mode 100644 index 0000000..3e530f2 --- /dev/null +++ b/kmipclient/include/kmipclient_version.hpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIPCLIENT_VERSION_H +#define KMIPCLIENT_VERSION_H + +#include "libkmip_version.h" + +#define KMIPCLIENT_VERSION_MAJOR 0 +#define KMIPCLIENT_VERSION_MINOR 1 +#define KMIPCLIENT_VERSION_PATCH 1 + +#define KMIPCLIENT_STRINGIFY_I(x) #x +#define KMIPCLIENT_TOSTRING_I(x) KMIPCLIENT_STRINGIFY_I (x) + +#define KMIPCLIENT_VERSION_STR \ + KMIPCLIENT_TOSTRING_I (KMIPCLIENT_VERSION_MAJOR) \ + "." KMIPCLIENT_TOSTRING_I (KMIPCLIENT_VERSION_MINOR) "." KMIPCLIENT_TOSTRING_I (KMIPCLIENT_VERSION_PATCH) + +#endif // KMIPCLIENT_VERSION_H diff --git a/kmipclient/src/AttributesFactory.cpp b/kmipclient/src/AttributesFactory.cpp new file mode 100644 index 0000000..d3b2314 --- /dev/null +++ b/kmipclient/src/AttributesFactory.cpp @@ -0,0 +1,68 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ +#include + +#include "../include/kmip_exceptions.hpp" +#include "AttributesFactory.hpp" +#include "StringUtils.hpp" + +namespace kmipclient +{ + +attributes_t +kmipclient::AttributesFactory::parse (Attribute *attributes, size_t attribute_count) +{ + attributes_t res; + for (Attribute *attribute = attributes; attribute_count-- > 0; attribute++) + { + switch (attribute->type) + { + case KMIP_ATTR_UNIQUE_IDENTIFIER: + res[KMIP_ATTR_NAME_NAME] = "Not yet parsed"; + break; + case KMIP_ATTR_NAME: + { + const auto *ns = static_cast (attribute->value); + const auto *ts = static_cast (ns->value); + auto val = StringUtils::fromKmipText (ts); + res[KMIP_ATTR_NAME_NAME] = val; + } + break; + case KMIP_ATTR_STATE: + { + const auto *a = static_cast (attribute->value); + std::stringstream ss; + ss << *a; + res[KMIP_ATTR_NAME_STATE] = ss.str (); + } + break; + case KMIP_ATTR_OBJECT_GROUP: + { + const auto *ts = static_cast (attribute->value); + auto val = StringUtils::fromKmipText (ts); + res[KMIP_ATTR_NAME_GROUP] = val; + } + break; + default: + { + throw ErrorException ("Unknown attribute type, not converted"); + } + } + } + return res; +} +} \ No newline at end of file diff --git a/kmipclient/src/AttributesFactory.hpp b/kmipclient/src/AttributesFactory.hpp new file mode 100644 index 0000000..20aa57e --- /dev/null +++ b/kmipclient/src/AttributesFactory.hpp @@ -0,0 +1,34 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef ATTRIBUTESFACTORY_HPP +#define ATTRIBUTESFACTORY_HPP + +#include "kmip_data_types.hpp" +#include "kmip_structs.h" + +namespace kmipclient +{ +class AttributesFactory +{ +public: + AttributesFactory () = default; + static attributes_t parse (Attribute *attribute, size_t attribute_count); +}; +} + +#endif // ATTRIBUTESFACTORY_HPP diff --git a/kmipclient/src/IOUtils.cpp b/kmipclient/src/IOUtils.cpp new file mode 100644 index 0000000..442752b --- /dev/null +++ b/kmipclient/src/IOUtils.cpp @@ -0,0 +1,103 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "IOUtils.hpp" +#include "../include/kmip_exceptions.hpp" +#include "ResponseFactory.hpp" + +#include +#include + +namespace kmipclient +{ +#define KMIP_MSG_LENGTH_BYTES 8 + +void +IOUtils::send (KmipCtx &kmip_ctx) const +{ + const KMIP *ctx = kmip_ctx.get (); + int dlen = static_cast (ctx->index - ctx->buffer); + if (int sent = net_client.send (ctx->buffer, dlen); sent < dlen) + { + kmip_ctx.free_buffer (); + throw ErrorException (-1, std::format ("Can not send request. Bytes total: {}, bytes sent: {}", dlen, sent)); + } + kmip_ctx.free_buffer (); +} + +void +IOUtils::receive_message_in_ctx (KmipCtx &kmip_ctx) +{ + uint8_t msg_len_buf[KMIP_MSG_LENGTH_BYTES]; + + int received = net_client.recv (&msg_len_buf, KMIP_MSG_LENGTH_BYTES); + if (received < KMIP_MSG_LENGTH_BYTES) + { + kmip_ctx.free_buffer (); + throw ErrorException (-1, std::format ("Can not receive response length. Bytes total: {}, bytes received: {}", + KMIP_MSG_LENGTH_BYTES, received)); + } + + // this is ugly method to get message length!!! + kmip_ctx.set_buffer (msg_len_buf, KMIP_MSG_LENGTH_BYTES); + KMIP *ctx = kmip_ctx.get (); + ctx->index += 4; + int length = 0; + kmip_decode_int32_be (ctx, &length); + // + if (length > ctx->max_message_size) + { + throw ErrorException (-1, std::format ("Message too long. Length: {}", length)); + } + // TODO: deallocate buffer + kmip_ctx.alloc_buffer (KMIP_MSG_LENGTH_BYTES + length); + memcpy (ctx->buffer, msg_len_buf, KMIP_MSG_LENGTH_BYTES); + received = net_client.recv (ctx->buffer + KMIP_MSG_LENGTH_BYTES, length); + if (received < length) + { + kmip_ctx.free_buffer (); + throw ErrorException ( + -1, std::format ("Can not receive response. Bytes total: {}, bytes received: {}", length, received)); + } + if (logger != nullptr) + { + logger->log (ERROR, print_response ()); + } +} + +void +IOUtils::do_exchange (KmipCtx &kmip_ctx) +{ + send (kmip_ctx); + receive_message_in_ctx (kmip_ctx); +} + +std::string +IOUtils::print_request () +{ + // TODO: implement request text representation + return "NOT_IMPLEMENTED"; +} + +std::string +IOUtils::print_response () +{ + // TODO: implement response text representation + return "NOT_IMPLEMENTED"; +} + +} // namespace diff --git a/kmipclient/src/IOUtils.hpp b/kmipclient/src/IOUtils.hpp new file mode 100644 index 0000000..09ff0af --- /dev/null +++ b/kmipclient/src/IOUtils.hpp @@ -0,0 +1,51 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef IOUTILS_HPP +#define IOUTILS_HPP + +#include + +#include "KmipCtx.hpp" +#include "Logger.hpp" +#include "NetClient.hpp" + +namespace kmipclient +{ + +class IOUtils +{ + +public: + explicit IOUtils (NetClient &nc) : net_client (nc) {}; + explicit IOUtils (NetClient &nc, const std::shared_ptr &log) : net_client (nc) { logger = log; }; + + void do_exchange (KmipCtx &kmip_ctx); + // log for debug purposes, not implemented yet + std::string print_request (); + std::string print_response (); + +private: + void send (KmipCtx &kmip_ctx) const; + void receive_message_in_ctx (KmipCtx &kmip_ctx); + NetClient &net_client; + std::shared_ptr logger; +}; + +} // namespace + +#endif // IOUTILS_HPP diff --git a/kmipclient/src/Key.cpp b/kmipclient/src/Key.cpp new file mode 100644 index 0000000..72c7c8e --- /dev/null +++ b/kmipclient/src/Key.cpp @@ -0,0 +1,282 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Key.hpp" +#include "../include/kmip_exceptions.hpp" +#include "StringUtils.hpp" +#include "kmip.h" +#include "kmip_data_types.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace kmipclient +{ + +namespace +{ +// Try to parse BIO as X509 certificate and return Key if successful +std::optional +try_parse_certificate (BIO *bio) +{ + X509 *cert = PEM_read_bio_X509 (bio, nullptr, nullptr, nullptr); + if (!cert) + return std::nullopt; + + EVP_PKEY *pkey = X509_get_pubkey (cert); + if (!pkey) + { + X509_free (cert); + return std::nullopt; + } + + unsigned char *der = nullptr; + int der_len = i2d_PUBKEY (pkey, &der); + EVP_PKEY_free (pkey); + X509_free (cert); + + if (der_len <= 0) + { + if (der) + OPENSSL_free (der); + return std::nullopt; + } + + std::vector key_bytes (der, der + der_len); + OPENSSL_free (der); + + attributes_t attrs; + attrs[KMIP_ATTR_NAME_NAME] = "certificate_public_key"; + return Key (key_bytes, KeyType::PUBLIC_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_UNSET, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, attrs); +} + +// Try to parse BIO as private key +std::optional +try_parse_private_key (BIO *bio) +{ + EVP_PKEY *pkey = PEM_read_bio_PrivateKey (bio, nullptr, nullptr, nullptr); + if (!pkey) + return std::nullopt; + + unsigned char *der = nullptr; + int der_len = i2d_PrivateKey (pkey, &der); + EVP_PKEY_free (pkey); + + if (der_len <= 0) + { + if (der) + OPENSSL_free (der); + return std::nullopt; + } + + std::vector key_bytes (der, der + der_len); + OPENSSL_free (der); + + attributes_t attrs; + attrs[KMIP_ATTR_NAME_NAME] = "private_key"; + return Key (key_bytes, KeyType::PRIVATE_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_UNSET, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, attrs); +} + +// Try to parse BIO as public key +std::optional +try_parse_public_key (BIO *bio) +{ + EVP_PKEY *pkey = PEM_read_bio_PUBKEY (bio, nullptr, nullptr, nullptr); + if (!pkey) + return std::nullopt; + + unsigned char *der = nullptr; + int der_len = i2d_PUBKEY (pkey, &der); + EVP_PKEY_free (pkey); + + if (der_len <= 0) + { + if (der) + OPENSSL_free (der); + return std::nullopt; + } + + std::vector key_bytes (der, der + der_len); + OPENSSL_free (der); + + attributes_t attrs; + attrs[KMIP_ATTR_NAME_NAME] = "public_key"; + return Key (key_bytes, KeyType::PUBLIC_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_UNSET, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, attrs); +} + +// Try to detect an AES/raw key encoded in PEM-like text by extracting base64 between headers +std::optional +try_parse_aes_from_pem_text (const std::string &pem) +{ + // Find the first PEM header and footer lines, extract base64 content between them + std::istringstream iss (pem); + std::string line; + bool in_pem = false; + std::string b64; + while (std::getline (iss, line)) + { + if (!in_pem) + { + if (line.rfind ("-----BEGIN", 0) == 0) + { + in_pem = true; + } + } + else + { + if (line.rfind ("-----END", 0) == 0) + break; + // skip header/footer and empty lines + if (line.empty ()) + continue; + b64 += line; + } + } + + if (b64.empty ()) + return std::nullopt; + + try + { + auto decoded = StringUtils::fromBase64 (b64); + size_t size = decoded.size (); + if (size == 16 || size == 24 || size == 32) + { + return Key (decoded, KeyType::SYMMETRIC_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_AES, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, {}); + } + } + catch (...) // any parsing errors + { + return std::nullopt; + } + + return std::nullopt; +} +} // anonymous namespace + + +Key +Key::aes_from_hex (const std::string &hex) +{ + auto hex_parsed = StringUtils::fromHex (hex); + size_t size = hex_parsed.size (); + // Expect AES key sizes in bytes: 16 (128 bits), 24 (192 bits), 32 (256 bits) + if (size != 16 && size != 24 && size != 32) + { + throw ErrorException{ -1, std::string ("Invalid AES key length: ") + std::to_string (size * 8) + + " bits. Should be 128, 192 or 256 bits" }; + } + return Key (hex_parsed, KeyType::SYMMETRIC_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_AES, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, {}); +} + +Key +Key::aes_from_base64 (const std::string &base64) +{ + auto parsed = StringUtils::fromBase64 (base64); + size_t size = parsed.size (); + if (size != 16 && size != 24 && size != 32) + { + throw ErrorException{ -1, std::string ("Invalid AES key length: ") + std::to_string (size * 8) + + " bits. Should be 128, 192 or 256 bits" }; + } + return Key (parsed, KeyType::SYMMETRIC_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_AES, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, {}); +} + +Key +Key::aes_from_value (const std::vector &val) +{ + size_t size = val.size (); + if (size != 16 && size != 24 && size != 32) + { + throw ErrorException{ -1, std::string ("Invalid AES key length: ") + std::to_string (size * 8) + + " bits. Should be 128, 192 or 256 bits" }; + } + return Key (val, KeyType::SYMMETRIC_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_AES, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, {}); +} + +Key +Key::from_PEM (const std::string &pem) +{ + // 1) Try as certificate + BIO *bio = BIO_new_mem_buf (pem.data (), static_cast (pem.size ())); + if (!bio) + throw ErrorException ("Failed to create BIO for PEM data"); + + if (auto cert_key = try_parse_certificate (bio); cert_key.has_value ()) + { + BIO_free (bio); + return cert_key.value (); + } + + (void)BIO_reset (bio); + if (auto priv_key = try_parse_private_key (bio); priv_key.has_value ()) + { + BIO_free (bio); + return priv_key.value (); + } + + (void)BIO_reset (bio); + if (auto pub_key = try_parse_public_key (bio); pub_key.has_value ()) + { + BIO_free (bio); + return pub_key.value (); + } + + BIO_free (bio); + + // 2) Try to detect an AES/raw key encoded in PEM text (base64 between headers) + if (auto aes_key = try_parse_aes_from_pem_text (pem); aes_key.has_value ()) + return aes_key.value (); + + throw ErrorException (KMIP_NOT_IMPLEMENTED, "Unsupported PEM format or not implemented"); +} + +Key +Key::generate_aes (size_t size_bits) +{ + if (size_bits != 128 && size_bits != 192 && size_bits != 256) + { + throw ErrorException ("Unsupported AES key size. Use 128, 192 or 256 bits"); + } + + size_t size_bytes = size_bits / 8; + std::vector buf (size_bytes); + if (1 != RAND_bytes (buf.data (), static_cast (size_bytes))) + { + unsigned long err = ERR_get_error (); + char err_buf[256]; + ERR_error_string_n (err, err_buf, sizeof (err_buf)); + throw ErrorException (std::string ("OpenSSL RAND_bytes failed: ") + err_buf); + } + + return Key (buf, KeyType::SYMMETRIC_KEY, cryptographic_algorithm::KMIP_CRYPTOALG_AES, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, {}); +} +} \ No newline at end of file diff --git a/kmipclient/src/KeyFactory.cpp b/kmipclient/src/KeyFactory.cpp new file mode 100644 index 0000000..7dc125f --- /dev/null +++ b/kmipclient/src/KeyFactory.cpp @@ -0,0 +1,67 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "KeyFactory.hpp" +#include "../include/kmip_exceptions.hpp" +#include "AttributesFactory.hpp" + +namespace kmipclient +{ + +Key +kmipclient::KeyFactory::parse_response (const GetResponsePayload *pld) +{ + switch (pld->object_type) + { + case KMIP_OBJTYPE_SYMMETRIC_KEY: + { + auto *symmetric_key = static_cast (pld->object); + KeyBlock *block = symmetric_key->key_block; + if ((block->key_format_type != KMIP_KEYFORMAT_RAW) || (block->key_wrapping_data != nullptr)) + { + throw ErrorException (KMIP_INVALID_ENCODING, "Invalid response object format."); + } + auto block_value = static_cast (block->key_value); + auto material = static_cast (block_value->key_material); + + key_t kv (material->value, material->value + material->size); + // Do we have some other attributes here with any KMIP server? block_value->attribute_count is 0 + auto key_attributes = AttributesFactory::parse (block_value->attributes, block_value->attribute_count); + Key key (kv, KeyType::SYMMETRIC_KEY, block->cryptographic_algorithm, + cryptographic_usage_mask::KMIP_CRYPTOMASK_UNSET, key_attributes); + + return key; + } + case KMIP_OBJTYPE_PRIVATE_KEY: + { + throw ErrorException (KMIP_NOT_IMPLEMENTED, "NOT IMPLEMENTED"); + } + case KMIP_OBJTYPE_PUBLIC_KEY: + { + throw ErrorException (KMIP_NOT_IMPLEMENTED, "NOT IMPLEMENTED"); + } + case KMIP_OBJTYPE_CERTIFICATE: + { + throw ErrorException (KMIP_NOT_IMPLEMENTED, "NOT IMPLEMENTED"); + } + default: + { + throw ErrorException (KMIP_NOT_IMPLEMENTED, "NOT IMPLEMENTED"); + } + } +} +} \ No newline at end of file diff --git a/kmipclient/src/KeyFactory.hpp b/kmipclient/src/KeyFactory.hpp new file mode 100644 index 0000000..2b3fedb --- /dev/null +++ b/kmipclient/src/KeyFactory.hpp @@ -0,0 +1,35 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KEY_FACTORY_HPP +#define KEY_FACTORY_HPP + +#include "Key.hpp" +#include "kmip_structs.h" + +namespace kmipclient +{ +class KeyFactory +{ +public: + KeyFactory () = default; + static Key parse_response (const GetResponsePayload *pld); +}; + +} + +#endif // KEY_FACTORY_HPP diff --git a/kmipclient/src/KmipClient.cpp b/kmipclient/src/KmipClient.cpp new file mode 100644 index 0000000..7d190d5 --- /dev/null +++ b/kmipclient/src/KmipClient.cpp @@ -0,0 +1,215 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "KmipClient.hpp" + +#include "IOUtils.hpp" +#include "KmipCtx.hpp" +#include "RequestFactory.hpp" +#include "ResponseFactory.hpp" + +namespace kmipclient +{ + +KmipClient::KmipClient (NetClient &net_client) + : net_client (net_client), io (std::make_unique (net_client)) {}; + +KmipClient::KmipClient (NetClient &net_client, const std::shared_ptr &log) + : net_client (net_client), logger (log), io (std::make_unique (net_client)) +{ +} + +KmipClient::~KmipClient () { net_client.close (); }; + +id_t +KmipClient::op_register_key (const name_t &name, const name_t &group, const Key &k) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_register_key_rq (ctx, name, group, k); + io->do_exchange (ctx); + return rf.get_id (0); +} + +id_t +KmipClient::op_register_secret (const name_t &name, const name_t &group, const std::string_view secret, + enum secret_data_type secret_type) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_register_secret_rq (ctx, name, group, secret, secret_type); + io->do_exchange (ctx); + return rf.get_id (0); +} + +id_t +KmipClient::op_create_aes_key (const name_t &name, const name_t &group) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_create_aes_rq (ctx, name, group); + io->do_exchange (ctx); + return rf.get_id (0); +} + +Key +KmipClient::op_get_key (const id_t &id) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_get_rq (ctx, id); + io->do_exchange (ctx); + + auto key = rf.get_key (0); + // TODO: this is temporary solution, we'll use multiple batch items in the future + attributes_t attrs = op_get_attributes (id, { KMIP_ATTR_NAME_STATE }); + key.set_attribute (KMIP_ATTR_NAME_STATE, attrs[KMIP_ATTR_NAME_STATE]); + return key; +} + +Secret +KmipClient::op_get_secret (const id_t &id) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_get_rq (ctx, id); + io->do_exchange (ctx); + return rf.get_secret (0); +} + +id_t +KmipClient::op_activate (const id_t &id) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_activate_rq (ctx, id); + io->do_exchange (ctx); + return rf.get_id (0); +} +names_t +KmipClient::op_get_attribute_list (const id_t &id) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_get_attribute_list_rq (ctx, id); + io->do_exchange (ctx); + return rf.get_attribute_names (0); +} + +attributes_t +KmipClient::op_get_attributes (const id_t &id, const std::vector &attr_names) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_get_attributes_rq (ctx, id, attr_names); + io->do_exchange (ctx); + return rf.get_attributes (0); +} + +ids_t +KmipClient::op_locate_by_name (const name_t &name, enum object_type o_type) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + // actually, with Vault server there should be only one item with the name + RequestFactory::create_locate_by_name_rq (ctx, name, o_type, MAX_ITEMS_IN_BATCH, 0); + io->do_exchange (ctx); + return rf.get_ids (0); +} + +ids_t +KmipClient::op_locate_by_group (const name_t &group, enum object_type o_type, size_t max_ids) const +{ + + KmipCtx ctx; + ResponseFactory rf (ctx); + ids_t result; + size_t received = 0; + size_t offset = 0; + do + { + RequestFactory::create_locate_by_group_rq (ctx, group, o_type, MAX_ITEMS_IN_BATCH, offset); + io->do_exchange (ctx); + auto exp = rf.get_ids (0); + + if (ids_t got = exp; !got.empty ()) + { + received = got.size (); + offset += got.size (); + result.insert (result.end (), got.begin (), got.end ()); + } + else + { + break; + } + } + while (received == MAX_ITEMS_IN_BATCH && result.size () < max_ids); + return result; +} + +ids_t +KmipClient::op_all (enum object_type o_type, size_t max_ids) const +{ + + KmipCtx ctx; + ResponseFactory rf (ctx); + ids_t result; + size_t received = 0; + size_t offset = 0; + do + { + RequestFactory::create_locate_all_rq (ctx, o_type, MAX_ITEMS_IN_BATCH, offset); + io->do_exchange (ctx); + auto exp = rf.get_ids (0); + if (ids_t got = exp; !got.empty ()) + { + received = got.size (); + offset += got.size (); + result.insert (result.end (), got.begin (), got.end ()); + } + else + { + break; + } + } + while (received == MAX_ITEMS_IN_BATCH && result.size () < max_ids); + return result; +} + +id_t +KmipClient::op_revoke (const id_t &id, enum revocation_reason_type reason, const name_t &message, + time_t occurrence_time) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + + RequestFactory::create_revoke_rq (ctx, id, reason, message, occurrence_time); + io->do_exchange (ctx); + return rf.get_id (0); +} + +id_t +KmipClient::op_destroy (const id_t &id) const +{ + KmipCtx ctx; + ResponseFactory rf (ctx); + RequestFactory::create_destroy_rq (ctx, id); + io->do_exchange (ctx); + return rf.get_id (0); +} + +} diff --git a/kmipclient/src/KmipCtx.hpp b/kmipclient/src/KmipCtx.hpp new file mode 100644 index 0000000..f452eb2 --- /dev/null +++ b/kmipclient/src/KmipCtx.hpp @@ -0,0 +1,180 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIPCTX_HPP +#define KMIPCTX_HPP + +#include "kmip.h" +#include "kmip_data_types.hpp" + +#include + +#include +#include + +namespace kmipclient +{ + +class KmipCtx +{ +public: + /** + * Initializes KMIP context with default version 1.4 */ + KmipCtx () : KmipCtx (KMIP_PROTOCOL_VERSION_DEFAULT) {}; + /** + * Initializes KMIP context with version + */ + explicit KmipCtx (enum kmip_version version) + { + kmip_init (&m_ctx, nullptr, 0, version); + alloc_buffer (); + }; + /** + * Destroys KMIP context + */ + ~KmipCtx () + { + free_buffer (); + kmip_destroy (&m_ctx); + }; + /** + * get raw KMIP ctx pointer + * @return raw KMIP ctx pointer + */ + // no copy, no move + KmipCtx (const KmipCtx &other) = delete; + KmipCtx (KmipCtx &&other) noexcept = delete; + KmipCtx &operator= (const KmipCtx &other) = delete; + KmipCtx &operator= (KmipCtx &&other) noexcept = delete; + + KMIP *get (); + void increase_buffer (); + void alloc_buffer (); + void alloc_buffer (size_t buf_size); + void free_buffer (); + void set_buffer (uint8_t *buf, size_t buffer_total_size); + [[nodiscard]] std::string get_errors () const; + + template + [[nodiscard]] T * + allocate () + { + return static_cast (m_ctx.calloc_func (m_ctx.state, 1, sizeof (T))); + } + + void free (void *p) const; + + TextString *from_string (const std::string &str); + +private: + int buffer_blocks = 1; + const int buffer_block_size = 1024; + KMIP m_ctx{}; +}; + +inline KMIP * +KmipCtx::get () +{ + return &m_ctx; +}; + +void inline KmipCtx::free (void *p) const { m_ctx.free_func (m_ctx.state, p); } + +void inline KmipCtx::increase_buffer () +{ + uint8 *encoding = m_ctx.buffer; + + kmip_reset (&m_ctx); + m_ctx.free_func (m_ctx.state, encoding); + + buffer_blocks += 1; + int buffer_total_size = buffer_blocks * buffer_block_size; + + encoding = static_cast (m_ctx.calloc_func (m_ctx.state, buffer_blocks, buffer_block_size)); + if (encoding == nullptr) + { + kmip_destroy (&m_ctx); + throw std::bad_alloc (); + } + + kmip_set_buffer (&m_ctx, encoding, buffer_total_size); +} + +void inline KmipCtx::alloc_buffer (size_t buf_size) +{ + auto *buffer = static_cast (m_ctx.calloc_func (m_ctx.state, 1, buf_size)); + if (buffer == nullptr) + { + kmip_destroy (&m_ctx); + throw std::bad_alloc (); + } + m_ctx.memset_func (buffer, 0, buf_size); + kmip_set_buffer (&m_ctx, buffer, buf_size); +} + +void inline KmipCtx::alloc_buffer () +{ + int buffer_total_size = buffer_blocks * buffer_block_size; + auto *buffer = static_cast (m_ctx.calloc_func (m_ctx.state, buffer_blocks, buffer_block_size)); + if (buffer == nullptr) + { + kmip_destroy (&m_ctx); + throw std::bad_alloc (); + } + m_ctx.memset_func (buffer, 0, buffer_total_size); + kmip_set_buffer (&m_ctx, buffer, buffer_total_size); +} + +void inline KmipCtx::free_buffer () +{ + kmip_free_buffer (&m_ctx, m_ctx.buffer, m_ctx.size); + kmip_set_buffer (&m_ctx, nullptr, 0); + buffer_blocks = 1; +} + +void inline KmipCtx::set_buffer (uint8_t *buf, size_t buffer_total_size) +{ + free_buffer (); + kmip_set_buffer (&m_ctx, buf, buffer_total_size); +} + +std::string inline KmipCtx::get_errors () const +{ + std::string errors; + ErrorFrame *index = m_ctx.frame_index; + do + { + errors.append (std::format ("- %s @ line: %d\n", index->function, index->line)); + } + while (index-- != m_ctx.errors); + + return errors; +} + +inline TextString * +KmipCtx::from_string (const std::string &str) +{ + auto res = allocate (); + res->size = str.size (); + res->value = static_cast (m_ctx.calloc_func (m_ctx.state, 1, res->size)); + strncpy (res->value, str.c_str (), res->size); + return res; +} + +}; + +#endif // KMIPCTX_HPP diff --git a/kmipclient/src/KmipRequest.hpp b/kmipclient/src/KmipRequest.hpp new file mode 100644 index 0000000..2a6bee0 --- /dev/null +++ b/kmipclient/src/KmipRequest.hpp @@ -0,0 +1,93 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef KMIPREQUEST_HPP +#define KMIPREQUEST_HPP + +#include "../include/kmip_exceptions.hpp" +#include "KmipCtx.hpp" +#include + +namespace kmipclient +{ +class KmipRequest +{ +public: + explicit KmipRequest (KmipCtx &ctx); + + RequestMessage & + get () + { + return request; + }; + void add_batch_item (RequestBatchItem *bi); + void encode () const; + [[nodiscard]] KmipCtx & + get_ctx () const + { + return ctx_; + }; + +private: + RequestMessage request{}; + RequestHeader rh{}; + ProtocolVersion pv{}; + KmipCtx &ctx_; +}; + +inline KmipRequest::KmipRequest (KmipCtx &ctx) : ctx_ (ctx) +{ + kmip_init_protocol_version (&pv, ctx_.get ()->version); + kmip_init_request_header (&rh); + rh.protocol_version = &pv; + rh.maximum_response_size = ctx_.get ()->max_message_size; + rh.time_stamp = time (nullptr); + rh.batch_count = 0; + request.request_header = &rh; +}; + +inline void +KmipRequest::add_batch_item (RequestBatchItem *rbi) +{ + // Sorry, C++ guys, we have to use address arithmetic here because of the lower level + *(&request.batch_items + request.batch_count) = rbi; + request.batch_count += 1; + request.request_header->batch_count += 1; +} + +inline void +KmipRequest::encode () const +{ + /* Encode the request message. Dynamically resize the encoding buffer */ + /* if it's not big enough. Once encoding succeeds, send the request */ + /* message. */ + + int encode_result = kmip_encode_request_message (ctx_.get (), &request); + while (encode_result == KMIP_ERROR_BUFFER_FULL) + { + ctx_.increase_buffer (); + encode_result = kmip_encode_request_message (ctx_.get (), &request); + } + if (encode_result != KMIP_OK) + { + // very low probability, usually we have plenty of memory + throw ErrorException (encode_result, "Error in the KMIP request encoding"); + } +} + +} +#endif // KMIPREQUEST_HPP diff --git a/kmipclient/src/NetClientOpenSSL.cpp b/kmipclient/src/NetClientOpenSSL.cpp new file mode 100644 index 0000000..2089d21 --- /dev/null +++ b/kmipclient/src/NetClientOpenSSL.cpp @@ -0,0 +1,132 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "NetClientOpenSSL.hpp" + +#include "../include/kmip_exceptions.hpp" +#include "kmip_data_types.hpp" +#include +#include + +namespace kmipclient +{ + +bool +NetClientOpenSSL::check_connected () +{ + if (is_connected ()) + { + return true; + } + else + { + return connect (); + } +} + +NetClientOpenSSL::NetClientOpenSSL (const std::string host, const std::string port, const std::string clientCertificateFn, + const std::string clientKeyFn, const std::string serverCaCertFn, int timeout_ms) + : NetClient (host, port, clientCertificateFn, clientKeyFn, serverCaCertFn, timeout_ms) +{ +} + +NetClientOpenSSL::~NetClientOpenSSL () { NetClientOpenSSL::close (); } + +bool +NetClientOpenSSL::connect () +{ + ctx_ = SSL_CTX_new (SSLv23_method ()); + + if (SSL_CTX_use_certificate_file (ctx_, m_clientCertificateFn.c_str (), SSL_FILETYPE_PEM) != 1) + { + SSL_CTX_free (ctx_); + ctx_ = nullptr; + throw ErrorException (-1, "Loading the client certificate failed from file: " + m_clientCertificateFn); + } + if (SSL_CTX_use_PrivateKey_file (ctx_, m_clientKeyFn.c_str (), SSL_FILETYPE_PEM) != 1) + { + SSL_CTX_free (ctx_); + ctx_ = nullptr; + throw ErrorException (-1, "Loading the client key failed from file: " + m_clientKeyFn); + } + if (SSL_CTX_load_verify_locations (ctx_, m_serverCaCertificateFn.c_str (), nullptr) != 1) + { + SSL_CTX_free (ctx_); + ctx_ = nullptr; + throw ErrorException (-1, "Loading the server certificate failed from file: " + m_serverCaCertificateFn); + } + + bio_ = BIO_new_ssl_connect (ctx_); + if (bio_ == nullptr) + { + SSL_CTX_free (ctx_); + throw ErrorException (-1, "BIO_new_ssl_connect failed"); + } + + SSL *ssl = nullptr; + BIO_get_ssl (bio_, &ssl); + SSL_set_mode (ssl, SSL_MODE_AUTO_RETRY); + BIO_set_conn_hostname (bio_, m_host.c_str ()); + BIO_set_conn_port (bio_, m_port.c_str ()); + BIO_set_ssl_renegotiate_timeout (bio_, m_timeout_ms); + if (BIO_do_connect (bio_) != 1) + { + BIO_free_all (bio_); + SSL_CTX_free (ctx_); + bio_ = nullptr; + ctx_ = nullptr; + throw ErrorException (-1, "BIO_do_connect failed"); + } + m_isConnected = true; + return m_isConnected; +} + +void +NetClientOpenSSL::close () +{ + if (bio_ != nullptr) + { + BIO_free_all (bio_); + bio_ = nullptr; + } + if (ctx_ != nullptr) + { + SSL_CTX_free (ctx_); + ctx_ = nullptr; + } + m_isConnected = false; +} + +int +NetClientOpenSSL::send (const void *data, int dlen) +{ + if (!check_connected ()) + { + return -1; + } + return BIO_write (bio_, data, dlen); +} + +int +NetClientOpenSSL::recv (void *data, int dlen) +{ + if (!check_connected ()) + return -1; + return BIO_read (bio_, data, dlen); +} + +} // namespace diff --git a/kmipclient/src/RequestFactory.cpp b/kmipclient/src/RequestFactory.cpp new file mode 100644 index 0000000..ba29248 --- /dev/null +++ b/kmipclient/src/RequestFactory.cpp @@ -0,0 +1,494 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "RequestFactory.hpp" + +#include "KmipCtx.hpp" +#include "KmipRequest.hpp" +#include "kmip.h" + +#include + +namespace kmipclient +{ + +void +RequestFactory::create_get_rq (KmipCtx &ctx, const id_t &id) +{ + KmipRequest rq (ctx); + + TextString uuid = {}; + uuid.size = id.size (); + uuid.value = const_cast (id.c_str ()); + + GetRequestPayload grp{}; + grp.unique_identifier = &uuid; + + RequestBatchItem rbi{}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_GET; + rbi.request_payload = &grp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_activate_rq (KmipCtx &ctx, const id_t &id) +{ + KmipRequest rq (ctx); + + TextString uuid = {}; + uuid.size = id.size (); + uuid.value = const_cast (id.c_str ()); + + ActivateRequestPayload arp{}; + arp.unique_identifier = &uuid; + + RequestBatchItem rbi{}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_ACTIVATE; + rbi.request_payload = &arp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_create_aes_rq (KmipCtx &ctx, const name_t &name, const name_t &group) +{ + KmipRequest rq (ctx); + Attribute a[5]; + for (auto &i : a) + { + kmip_init_attribute (&i); + } + + enum cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES; + a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM; + a[0].value = &algorithm; + + int32 length = 256; + a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH; + a[1].value = &length; + + int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT; + a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK; + a[2].value = &mask; + + Name ts; + TextString ts2 = { nullptr, 0 }; + ts2.value = const_cast (name.c_str ()); + ts2.size = kmip_strnlen_s (ts2.value, 250); + ts.value = &ts2; + ts.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING; + a[3].type = KMIP_ATTR_NAME; + a[3].value = &ts; + + TextString gs2 = { nullptr, 0 }; + gs2.value = const_cast (group.c_str ()); + gs2.size = kmip_strnlen_s (gs2.value, 250); + a[4].type = KMIP_ATTR_OBJECT_GROUP; + a[4].value = &gs2; + + TemplateAttribute ta = {}; + ta.attributes = a; + ta.attribute_count = std::size (a); + + CreateRequestPayload crp = {}; + crp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY; + crp.template_attribute = &ta; + + RequestBatchItem rbi = {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_CREATE; + rbi.request_payload = &crp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_register_key_rq (KmipCtx &ctx, const name_t &name, const name_t &group, const Key &key) +{ + KmipRequest rq (ctx); + int attr_count; + + group.empty () ? attr_count = 4 : attr_count = 5; + + Attribute a[attr_count]; + for (int i = 0; i < attr_count; i++) + { + kmip_init_attribute (&a[i]); + } + + cryptographic_algorithm algorithm = KMIP_CRYPTOALG_AES; + a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM; + a[0].value = &algorithm; + int32 length = key.size () * 8; + a[1].type = KMIP_ATTR_CRYPTOGRAPHIC_LENGTH; + a[1].value = &length; + + int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT; + a[2].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK; + a[2].value = &mask; + + Name ts; + TextString ts2 = { nullptr, 0 }; + ts2.value = const_cast (name.c_str ()); + ts2.size = kmip_strnlen_s (ts2.value, 250); + ts.value = &ts2; + ts.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING; + a[3].type = KMIP_ATTR_NAME; + a[3].value = &ts; + + if (attr_count == 5) + { + TextString gs2 = { nullptr, 0 }; + gs2.value = const_cast (group.c_str ()); + gs2.size = kmip_strnlen_s (gs2.value, 250); + a[4].type = KMIP_ATTR_OBJECT_GROUP; + a[4].value = &gs2; + } + + TemplateAttribute ta = {}; + ta.attributes = a; + ta.attribute_count = attr_count; + RegisterRequestPayload crp = {}; + crp.object_type = KMIP_OBJTYPE_SYMMETRIC_KEY; + crp.template_attribute = &ta; + + KeyBlock kb; + crp.object.symmetric_key.key_block = &kb; + kmip_init_key_block (crp.object.symmetric_key.key_block); + crp.object.symmetric_key.key_block->key_format_type = KMIP_KEYFORMAT_RAW; + + ByteString bs; + bs.value = const_cast (key.value ().data ()); + bs.size = key.size (); + + KeyValue kv; + kv.key_material = &bs; + kv.attribute_count = 0; + kv.attributes = nullptr; + + crp.object.symmetric_key.key_block->key_value = &kv; + crp.object.symmetric_key.key_block->key_value_type = KMIP_TYPE_BYTE_STRING; + crp.object.symmetric_key.key_block->cryptographic_algorithm = KMIP_CRYPTOALG_AES; + crp.object.symmetric_key.key_block->cryptographic_length = key.size () * 8; + + RequestBatchItem rbi = {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_REGISTER; + rbi.request_payload = &crp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_register_secret_rq (KmipCtx &ctx, const name_t &name, const name_t &group, + const std::string_view &secret, int secret_type) +{ + KmipRequest rq (ctx); + + int attr_count; + group.empty () ? attr_count = 2 : attr_count = 3; + + Attribute a[attr_count]; + for (int i = 0; i < attr_count; i++) + { + kmip_init_attribute (&a[i]); + } + + int32 mask = KMIP_CRYPTOMASK_DERIVE_KEY | KMIP_CRYPTOMASK_EXPORT; + a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK; + a[0].value = &mask; + + Name ts; + TextString ts2 = {}; + ts2.value = const_cast (name.c_str ()); + ts2.size = kmip_strnlen_s (ts2.value, 250); + ts.value = &ts2; + ts.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING; + a[1].type = KMIP_ATTR_NAME; + a[1].value = &ts; + + if (attr_count == 3) + { + TextString gs2 = {}; + gs2.value = const_cast (group.c_str ()); + gs2.size = kmip_strnlen_s (gs2.value, 250); + a[2].type = KMIP_ATTR_OBJECT_GROUP; + a[2].value = &gs2; + } + + TemplateAttribute ta = {}; + ta.attributes = a; + ta.attribute_count = attr_count; + + RegisterRequestPayload crp = {}; + crp.object_type = KMIP_OBJTYPE_SECRET_DATA; + crp.template_attribute = &ta; + + crp.object.secret_data.secret_data_type = static_cast (secret_type); + + KeyBlock kb; + crp.object.secret_data.key_block = &kb; + kmip_init_key_block (crp.object.secret_data.key_block); + crp.object.secret_data.key_block->key_format_type = KMIP_KEYFORMAT_OPAQUE; + + ByteString bs; + bs.value = reinterpret_cast (const_cast (secret.data ())); + bs.size = secret.size (); + + KeyValue kv; + kv.key_material = &bs; + kv.attribute_count = 0; + kv.attributes = nullptr; + + crp.object.secret_data.key_block->key_value = &kv; + crp.object.secret_data.key_block->key_value_type = KMIP_TYPE_BYTE_STRING; + + RequestBatchItem rbi = {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_REGISTER; + rbi.request_payload = &crp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_revoke_rq (KmipCtx &ctx, const id_t &id, int reason, const name_t &message, + time_t occurrence_time) +{ + KmipRequest rq (ctx); + + RevokeRequestPayload rrp = {}; + + rrp.compromise_occurence_date = occurrence_time; + + RevocationReason revocation_reason = {}; + revocation_reason.reason = static_cast (reason); + + TextString msg = {}; + msg.value = const_cast (message.c_str ()); + msg.size = message.size (); + revocation_reason.message = &msg; + + rrp.revocation_reason = &revocation_reason; + + TextString uuid = {}; + uuid.value = const_cast (id.c_str ()); + uuid.size = id.size (); + rrp.unique_identifier = &uuid; + + RequestBatchItem rbi{}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_REVOKE; + rbi.request_payload = &rrp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_destroy_rq (KmipCtx &ctx, const id_t &id) +{ + KmipRequest rq (ctx); + + TextString idt = {}; + idt.value = const_cast (id.c_str ()); + idt.size = id.size (); + + DestroyRequestPayload drp = {}; + drp.unique_identifier = &idt; + + RequestBatchItem rbi = {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_DESTROY; + rbi.request_payload = &drp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_get_attributes_rq (KmipCtx &ctx, const id_t &id, const std::vector &attr_names) +{ + KmipRequest rq (ctx); + + TextString uuid = {}; + uuid.value = const_cast (id.c_str ()); + uuid.size = id.size (); + + GetAttributeRequestPayload grp = {}; + grp.unique_identifier = &uuid; + + // create an array of attributes + std::vector a_names; + if (!attr_names.empty ()) + { + for (const auto &attr_name : attr_names) + { + TextString an = {}; + an.value = const_cast (attr_name.c_str ()); + an.size = attr_name.size (); + a_names.push_back (an); + } + grp.attribute_name = &a_names[0]; + } + else + { + grp.attribute_name = nullptr; + } + + RequestBatchItem rbi = {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_GET_ATTRIBUTES; + rbi.request_payload = &grp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_get_attribute_list_rq (KmipCtx &ctx, const id_t &id) +{ + KmipRequest rq (ctx); + + TextString uuid = {}; + uuid.value = const_cast (id.c_str ()); + uuid.size = id.size (); + + GetAttributeListRequestPayload grp = {}; + + RequestBatchItem rbi = {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_GET_ATTRIBUTE_LIST; + rbi.request_payload = &grp; + + rq.add_batch_item (&rbi); + rq.encode (); +} + +void +RequestFactory::create_locate_by_name_rq (KmipCtx &ctx, const name_t &name, object_type o_type, const size_t max_items, + const size_t offset) +{ + create_locate_rq (ctx, false, name, o_type, max_items, offset); +} + +void +RequestFactory::create_locate_by_group_rq (KmipCtx &ctx, const name_t &group_name, object_type o_type, size_t max_items, + size_t offset) +{ + create_locate_rq (ctx, true, group_name, o_type, max_items, offset); +} +void +RequestFactory::create_locate_all_rq (KmipCtx &ctx, object_type o_type, size_t max_items, size_t offset) +{ + create_locate_rq (ctx, true, "", o_type, max_items, offset); +} + +void +RequestFactory::create_locate_rq (KmipCtx &ctx, bool is_group, const name_t &name, object_type o_type, size_t max_items, + size_t offset) +{ + KmipRequest rq (ctx); + + size_t attrib_count = name.empty () ? 1 : 2; + Attribute a[attrib_count]; + for (int i = 0; i < attrib_count; i++) + { + kmip_init_attribute (&a[i]); + } + + object_type loctype = o_type; + a[0].type = KMIP_ATTR_OBJECT_TYPE; + a[0].value = &loctype; + + if (attrib_count == 2) + { + Name a_name; + TextString ts = {}; + ts.value = const_cast (name.c_str ()); + ts.size = kmip_strnlen_s (ts.value, 250); + a_name.value = &ts; + a_name.type = KMIP_NAME_UNINTERPRETED_TEXT_STRING; + if (is_group) + { + a[1].type = KMIP_ATTR_OBJECT_GROUP; + a[1].value = &ts; + } + else + { + a[1].type = KMIP_ATTR_NAME; + a[1].value = &a_name; + } + } + + // TODO: this is a piece of bad code! Handle it later. + // copy input array to list + auto attribute_list = rq.get_ctx ().allocate (); + if (attribute_list == nullptr) + { + throw std::bad_alloc (); + } + for (size_t i = 0; i < attrib_count; i++) + { + auto item = rq.get_ctx ().allocate (); + if (item == nullptr) + { + throw std::bad_alloc (); + } + item->data = kmip_deep_copy_attribute (rq.get_ctx ().get (), &a[i]); + if (item->data == nullptr) + { + throw std::bad_alloc (); + } + kmip_linked_list_enqueue (attribute_list, item); + } + + LocateRequestPayload lrp = {}; + lrp.maximum_items = max_items; + lrp.offset_items = offset; + lrp.storage_status_mask = 0; + lrp.group_member_option = group_member_option::group_member_default; + lrp.attribute_list = attribute_list; + + RequestBatchItem rbi = {}; + kmip_init_request_batch_item (&rbi); + rbi.operation = KMIP_OP_LOCATE; + rbi.request_payload = &lrp; + + rq.add_batch_item (&rbi); + rq.encode (); + + // TODO: this is dealock of bad code from above + LinkedListItem *item = nullptr; + while ((item = kmip_linked_list_pop (attribute_list)) != nullptr) + { + kmip_free_attribute (rq.get_ctx ().get (), static_cast (item->data)); + free (item->data); + kmip_free_buffer (rq.get_ctx ().get (), item, sizeof (LinkedListItem)); + } + rq.get_ctx ().free (attribute_list); +} + +} // namespace diff --git a/kmipclient/src/RequestFactory.hpp b/kmipclient/src/RequestFactory.hpp new file mode 100644 index 0000000..7db85f8 --- /dev/null +++ b/kmipclient/src/RequestFactory.hpp @@ -0,0 +1,59 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef REQUESTFACTORY_HPP +#define REQUESTFACTORY_HPP + +#include "KmipCtx.hpp" +#include "Key.hpp" +#include "kmip_data_types.hpp" + +namespace kmipclient +{ + +/** + * Creates requests and encodes them into KmipCtx + */ + +class RequestFactory +{ +public: + static void create_get_rq (KmipCtx &ctx, const id_t &id); + static void create_activate_rq (KmipCtx &ctx, const id_t &id); + static void create_create_aes_rq (KmipCtx &ctx, const name_t &name, const name_t &group); + static void create_register_key_rq (KmipCtx &ctx, const name_t &name, const name_t &group, const Key &k); + static void create_register_secret_rq (KmipCtx &ctx, const name_t &name, const name_t &group, + const std::string_view &secret, int secret_data_type); + static void create_revoke_rq (KmipCtx &ctx, const id_t &id, int reason, const name_t &message, + time_t occurrence_time); + static void create_destroy_rq (KmipCtx &ctx, const id_t &id); + static void create_get_attributes_rq (KmipCtx &ctx, const id_t &id, const std::vector &attr_names); + static void create_get_attribute_list_rq (KmipCtx &ctx, const id_t &id); + static void create_locate_by_name_rq (KmipCtx &ctx, const name_t &name, object_type o_type, size_t max_items, + size_t offset); + static void create_locate_by_group_rq (KmipCtx &ctx, const name_t &group_name, object_type o_type, size_t max_items, + size_t offset); + static void create_locate_all_rq (KmipCtx &ctxm, object_type o_type, size_t max_items, size_t offset); + +private: + static void create_locate_rq (KmipCtx &ctx, bool is_group, const name_t &name, object_type o_type, size_t max_items, + size_t offset); +}; + +} // namespace + +#endif // REQUESTFACTORY_HPP diff --git a/kmipclient/src/ResponseFactory.hpp b/kmipclient/src/ResponseFactory.hpp new file mode 100644 index 0000000..c49f76f --- /dev/null +++ b/kmipclient/src/ResponseFactory.hpp @@ -0,0 +1,174 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RESPONSEFACTORY_HPP +#define RESPONSEFACTORY_HPP + +#include "../include/kmip_exceptions.hpp" +#include "KmipCtx.hpp" +#include "ResponseResult.hpp" +#include "kmip.h" + +namespace kmipclient +{ +#define LAST_RESULT_MAX_MESSAGE_SIZE 512 // could be big with HasiCorp Vault + +struct OperationResult +{ + enum operation operation; + enum result_status result_status; + enum result_reason result_reason; + char result_message[LAST_RESULT_MAX_MESSAGE_SIZE]; +}; +/** Purpose of this class is to process multiple response batch items + * and get results of a batch request items in proper form + * TODO: work in progress + */ +class ResponseFactory +{ +public: + explicit ResponseFactory (KmipCtx &ctx) : ctx_ (ctx) {}; + ~ResponseFactory () { kmip_free_response_message (ctx_.get (), &m_resp); } + // disable copy and move + ResponseFactory (const ResponseFactory &) = delete; + ResponseFactory (ResponseFactory &&) = delete; + ResponseFactory &operator= (const ResponseFactory &) = delete; + ResponseFactory &operator= (ResponseFactory &&) = delete; + + id_t + get_id (int item_idx) + { + return ResponseResult::get_id (get_response_items ()[item_idx]); + } + + Key + get_key (int item_idx) + { + return ResponseResult::get_key (get_response_items ()[item_idx]); + } + + Secret + get_secret (int item_idx) + { + return ResponseResult::get_secret (get_response_items ()[item_idx]); + } + + attributes_t + get_attributes (int item_idx) + { + return ResponseResult::get_attributes (get_response_items ()[item_idx]); + } + + names_t + get_attribute_names (int item_idx) + { + return ResponseResult::get_attribute_list (get_response_items ()[item_idx]); + } + + ids_t + get_ids (int item_idx) + { + return ResponseResult::get_ids (get_response_items ()[item_idx]); + } + +private: + void parse_response (); + std::vector get_response_items (); + static std::string get_operation_result (const ResponseBatchItem &value); + KmipCtx &ctx_; + ResponseMessage m_resp{}; + bool is_parsed = false; +}; + +inline void +ResponseFactory::parse_response () +{ + // decode response; + int decode_result = kmip_decode_response_message (ctx_.get (), &m_resp); + if (decode_result != KMIP_OK) + { + throw ErrorException{ decode_result, ctx_.get_errors () }; + } + is_parsed = true; +} + +inline std::vector +ResponseFactory::get_response_items () +{ + if (!is_parsed) + { + parse_response (); + } + + std::vector items; + if (m_resp.batch_count < 1) + { // something went wrong + throw ErrorException{ -1, "No response batch items from the server." }; + } + + for (int idx = 0; idx < m_resp.batch_count; idx++) + { + if (m_resp.batch_items[idx].result_status != KMIP_STATUS_SUCCESS) // error from the server + { + throw ErrorException (-1, get_operation_result (m_resp.batch_items[idx])); + } + items.push_back (&m_resp.batch_items[idx]); + } + return items; +} + +inline std::string +ResponseFactory::get_operation_result (const ResponseBatchItem &value) +{ + char *bp; + size_t size; + OperationResult last_result{}; + + last_result.operation = value.operation; + last_result.result_status = value.result_status; + last_result.result_reason = value.result_reason; + if (value.result_message) + { + kmip_copy_textstring (last_result.result_message, value.result_message, sizeof (last_result.result_message)); + } + else + { + last_result.result_message[0] = 0; + } + // we use C mem_stream instead of std::ostringstream because we have to use + // print functions from libkmip, which uses FILE* + FILE *mem_stream = open_memstream (&bp, &size); + fprintf (mem_stream, "Message: %s\nOperation: ", last_result.result_message); + fflush (mem_stream); + kmip_print_operation_enum (mem_stream, last_result.operation); + fflush (mem_stream); + fprintf (mem_stream, "; Result status: "); + fflush (mem_stream); + kmip_print_result_status_enum (mem_stream, last_result.result_status); + fflush (mem_stream); + fprintf (mem_stream, "; Result reason: "); + fflush (mem_stream); + kmip_print_result_reason_enum (mem_stream, last_result.result_reason); + fclose (mem_stream); + std::string res{ bp, size }; + free (bp); + return res; +} + +} + +#endif // RESPONSEFACTORY_HPP diff --git a/kmipclient/src/ResponseResult.cpp b/kmipclient/src/ResponseResult.cpp new file mode 100644 index 0000000..87d4735 --- /dev/null +++ b/kmipclient/src/ResponseResult.cpp @@ -0,0 +1,189 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "ResponseResult.hpp" +#include "KeyFactory.hpp" + +#include "AttributesFactory.hpp" +#include "StringUtils.hpp" + +#include "../include/kmip_exceptions.hpp" +#include "kmip.h" +#include "kmip_locate.h" + +namespace kmipclient +{ + +std::string +from_kmip_text (const TextString *s) +{ + return std::string{ s->value, s->size }; +} + +id_t +ResponseResult::get_id (const ResponseBatchItem *rbi) +{ + id_t id; + switch (rbi->operation) + { + case KMIP_OP_CREATE: + { + auto *pld = static_cast (rbi->response_payload); + id = std::string{ pld->unique_identifier->value, pld->unique_identifier->size }; + } + break; + case KMIP_OP_GET: + { + auto *pld = static_cast (rbi->response_payload); + id = std::string{ pld->unique_identifier->value, pld->unique_identifier->size }; + } + break; + case KMIP_OP_REGISTER: + { + auto *pld = static_cast (rbi->response_payload); + id = std::string{ pld->unique_identifier->value, pld->unique_identifier->size }; + } + break; + case KMIP_OP_ACTIVATE: + { + auto *pld = static_cast (rbi->response_payload); + id = std::string{ pld->unique_identifier->value, pld->unique_identifier->size }; + } + break; + case KMIP_OP_REVOKE: + { + const auto *pld = static_cast (rbi->response_payload); + id = std::string{ pld->unique_identifier->value, pld->unique_identifier->size }; + } + break; + case KMIP_OP_DESTROY: + { + const auto *pld = static_cast (rbi->response_payload); + id = std::string{ pld->unique_identifier->value, pld->unique_identifier->size }; + } + break; + // TODO: other operations + default: + throw ErrorException (KMIP_NOT_IMPLEMENTED, "NOT IMPLEMENTED"); + } + return id; +} + +Key +ResponseResult::get_key (const ResponseBatchItem *rbi) +{ + auto *pld = static_cast (rbi->response_payload); + switch (pld->object_type) + { + // name known to KeyFactory key types + case KMIP_OBJTYPE_SYMMETRIC_KEY: + case KMIP_OBJTYPE_PUBLIC_KEY: + case KMIP_OBJTYPE_PRIVATE_KEY: + case KMIP_OBJTYPE_CERTIFICATE: + { + return KeyFactory::parse_response (pld); + }; + default: + throw ErrorException ("Invalid or unknown response object type."); + } +} + +Secret +ResponseResult::get_secret (const ResponseBatchItem *rbi) +{ + if (auto *pld = static_cast (rbi->response_payload); + pld->object_type != KMIP_OBJTYPE_SECRET_DATA) + { + throw ErrorException (KMIP_REASON_INVALID_DATA_TYPE, "Secret data expected"); + } + else + { + auto *secret = static_cast (pld->object); + KeyBlock *block = secret->key_block; + if (!(block->key_format_type != KMIP_KEYFORMAT_OPAQUE || block->key_format_type != KMIP_KEYFORMAT_RAW) + || (block->key_wrapping_data != nullptr)) + { + throw ErrorException (KMIP_OBJECT_MISMATCH, "Secret data key block format mismatch"); + } + + auto block_value = static_cast (block->key_value); + auto *material = static_cast (block_value->key_material); + size_t secret_size = material->size; + char result_key[secret_size]; + for (int i = 0; i < secret_size; i++) + { + result_key[i] = static_cast (material->value[i]); + } + // TODO: State attribute should be in the key response but it is empty. How to read a state from kmip? RBI? + return Secret{ result_key, KMIP_STATE_PRE_ACTIVE, secret->secret_data_type }; + } +} + +attributes_t +ResponseResult::get_attributes (const ResponseBatchItem *rbi) +{ + auto *pld = static_cast (rbi->response_payload); + + Attribute *attribute = pld->attribute; + // TODO: how to read multiple attributes? How to get attribute count? + // Solution: re-implement parsing in C++ or change to linked list in kmip.c + return AttributesFactory::parse (attribute, 1); +} + +names_t +ResponseResult::get_attribute_list (const ResponseBatchItem *rbi) +{ + names_t res; + auto *pld = static_cast (rbi->response_payload); + // TODO: process multiple + res.push_back (StringUtils::fromKmipText (pld->attribute_name)); + return res; +} + +void +copy_unique_ids (char ids[][MAX_LOCATE_LEN], size_t *id_size, const UniqueIdentifiers *value, const unsigned max_ids) +{ + size_t idx = 0; + if (value != nullptr) + { + LinkedListItem *curr = value->unique_identifier_list->head; + while (curr != nullptr && idx < max_ids) + { + kmip_copy_textstring (ids[idx], static_cast (curr->data), MAX_LOCATE_LEN - 1); + curr = curr->next; + idx++; + } + } + *id_size = idx; +} + +ids_t +ResponseResult::get_ids (const ResponseBatchItem *rbi) +{ + auto pld = static_cast (rbi->response_payload); + LocateResponse locate_result; + copy_unique_ids (locate_result.ids, &locate_result.ids_size, pld->unique_ids, MAX_LOCATE_IDS); + ids_t res; + for (int i = 0; i < locate_result.ids_size; ++i) + { + res.emplace_back (locate_result.ids[i]); + } + + return res; +} + +} \ No newline at end of file diff --git a/kmipclient/src/ResponseResult.hpp b/kmipclient/src/ResponseResult.hpp new file mode 100644 index 0000000..93604d8 --- /dev/null +++ b/kmipclient/src/ResponseResult.hpp @@ -0,0 +1,42 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RESPONSERESULT_HPP +#define RESPONSERESULT_HPP + +#include "KmipCtx.hpp" +#include "Key.hpp" +#include "kmip_data_types.hpp" + +#include "kmip.h" + +namespace kmipclient +{ +class ResponseResult +{ +public: + static id_t get_id (const ResponseBatchItem *rbi); + static Key get_key (const ResponseBatchItem *rbi); + static Secret get_secret (const ResponseBatchItem *rbi); + static attributes_t get_attributes (const ResponseBatchItem *rbi); + static names_t get_attribute_list (const ResponseBatchItem *rbi); + static ids_t get_ids (const ResponseBatchItem *rbi); +}; + +} + +#endif // RESPONSERESULT_HPP diff --git a/kmipclient/src/StringUtils.cpp b/kmipclient/src/StringUtils.cpp new file mode 100644 index 0000000..cf21b21 --- /dev/null +++ b/kmipclient/src/StringUtils.cpp @@ -0,0 +1,108 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include + +#include "StringUtils.hpp" + +#include "../include/kmip_exceptions.hpp" +namespace kmipclient +{ + +unsigned char +char2int (const char input) +{ + if (input >= '0' && input <= '9') + return input - '0'; + if (input >= 'A' && input <= 'F') + return input - 'A' + 10; + if (input >= 'a' && input <= 'f') + return input - 'a' + 10; + throw std::invalid_argument ("Invalid input string"); +} + +key_t +StringUtils::fromHex (const std::string &hex) +{ + if (hex.empty () || hex.size () % 2 != 0) + { + throw ErrorException{ "Invalid hex string length." }; + } + key_t bytes; + try + { + for (unsigned int i = 0; i < hex.length (); i += 2) + { + std::string byteString = hex.substr (i, 2); + auto byte = char2int (byteString.c_str ()[0]) * 16 + char2int (byteString.c_str ()[1]); + bytes.push_back (byte); + } + } + catch ([[maybe_unused]] const std::invalid_argument &e) + { + throw ErrorException{ "Invalid hex string length." }; + } + return bytes; +} + +std::vector +StringUtils::fromBase64 (const std::string &base64) +{ + static const std::array lookup = [] () { + std::array l{}; + l.fill (-1); + for (int i = 0; i < 64; ++i) + l["ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[i]] = i; + return l; + }(); + + std::vector out; + out.reserve ((base64.size () / 4) * 3); + + int val = 0, val_b = -8; + for (unsigned char c : base64) + { + if (lookup[c] == -1) + { + if (c == '=') + break; // Padding reached + continue; // Skip whitespace or invalid chars + } + val = (val << 6) + lookup[c]; + val_b += 6; + if (val_b >= 0) + { + out.push_back (static_cast ((val >> val_b) & 0xFF)); + val_b -= 8; + } + } + return out; +} + +std::string +StringUtils::fromKmipText (const TextString *ts) +{ + if (ts == nullptr || ts->size == 0) + { + return ""; + } + return std::string{ ts->value, ts->size }; +} + +} \ No newline at end of file diff --git a/kmipclient/src/StringUtils.hpp b/kmipclient/src/StringUtils.hpp new file mode 100644 index 0000000..0d76a4b --- /dev/null +++ b/kmipclient/src/StringUtils.hpp @@ -0,0 +1,37 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef STRINGUTILS_HPP +#define STRINGUTILS_HPP +#include "kmip_data_types.hpp" + +#include + +namespace kmipclient +{ + +class StringUtils +{ +public: + static key_t fromHex (const std::string &hex); + static std::string fromKmipText (const TextString *ts); + static std::vector fromBase64 (const std::string &base64); +}; + +} + +#endif // STRINGUTILS_HPP diff --git a/kmipclient/tests/KmipClientIntegrationTest.cpp b/kmipclient/tests/KmipClientIntegrationTest.cpp new file mode 100644 index 0000000..fff9972 --- /dev/null +++ b/kmipclient/tests/KmipClientIntegrationTest.cpp @@ -0,0 +1,718 @@ +/* Copyright (c) 2025 Percona LLC and/or its affiliates. All rights reserved. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; version 2 of + the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "Kmip.hpp" +#include "KmipClient.hpp" +#include "kmip_exceptions.hpp" +#include + +#include +#include +#include +#include +#include + +#define TEST_GROUP "tests" + +using namespace kmipclient; + + +static std::string TESTING_NAME_PREFIX = "tests_"; + + +// Helper class to manage environment variables +class KmipTestConfig +{ +public: + static KmipTestConfig & + getInstance () + { + static KmipTestConfig instance; + return instance; + } + + [[nodiscard]] bool + isConfigured () const + { + return !kmip_addr.empty () && !kmip_port.empty () && !kmip_client_ca.empty () && !kmip_client_key.empty () + && !kmip_server_ca.empty (); + } + + std::string kmip_addr; + std::string kmip_port; + std::string kmip_client_ca; + std::string kmip_client_key; + std::string kmip_server_ca; + int timeout_ms; + +private: + KmipTestConfig () + { + const char *addr = std::getenv ("KMIP_ADDR"); + const char *port = std::getenv ("KMIP_PORT"); + const char *client_ca = std::getenv ("KMIP_CLIENT_CA"); + const char *client_key = std::getenv ("KMIP_CLIENT_KEY"); + const char *server_ca = std::getenv ("KMIP_SERVER_CA"); + const char *timeout = std::getenv ("KMIP_TIMEOUT_MS"); + + if (addr) + kmip_addr = addr; + if (port) + kmip_port = port; + if (client_ca) + kmip_client_ca = client_ca; + if (client_key) + kmip_client_key = client_key; + if (server_ca) + kmip_server_ca = server_ca; + + timeout_ms = timeout ? std::atoi (timeout) : 5000; // Default 5 seconds + + if (!isConfigured ()) + { + std::cerr << "WARNING: KMIP environment variables not set. Tests will be skipped.\n" + << "Required variables:\n" + << " KMIP_ADDR\n" + << " KMIP_PORT\n" + << " KMIP_CLIENT_CA\n" + << " KMIP_CLIENT_KEY\n" + << " KMIP_SERVER_CA\n"; + } + } +}; + +// Base test fixture for KMIP integration tests +class KmipClientIntegrationTest : public ::testing::Test +{ +protected: + std::vector created_key_ids; + + void + SetUp () override + { + auto &config = KmipTestConfig::getInstance (); + + if (!config.isConfigured ()) + { + GTEST_SKIP () << "KMIP environment variables not configured"; + } + } + + void + TearDown () override + { + // Cleanup created keys if stored + auto &config = KmipTestConfig::getInstance (); + if (config.isConfigured () && !created_key_ids.empty ()) + { + try + { + Kmip kmip (config.kmip_addr.c_str (), config.kmip_port.c_str (), config.kmip_client_ca.c_str (), + config.kmip_client_key.c_str (), config.kmip_server_ca.c_str (), config.timeout_ms); + + for (const auto &key_id : created_key_ids) + { + // Try to destroy the key (best effort cleanup) + try + { + //if the object is not active then it cannot be revoked with reason other than KEY_COMPROMISE + auto res_r = kmip.client ().op_revoke (key_id, KEY_COMPROMISE, "Test cleanup", 0); + auto res_d = kmip.client ().op_destroy (key_id); + } + catch (ErrorException &e) + { + std::cerr << "Failed to destroy key: " << e.what () << std::endl; + } + } + } + catch (...) + { + // Ignore cleanup errors + } + } + } + + static std::unique_ptr + createKmipClient () + { + auto &config = KmipTestConfig::getInstance (); + return std::make_unique (config.kmip_addr.c_str (), config.kmip_port.c_str (), config.kmip_client_ca.c_str (), + config.kmip_client_key.c_str (), config.kmip_server_ca.c_str (), config.timeout_ms); + } + + void + trackKeyForCleanup (const std::string &key_id) + { + created_key_ids.push_back (key_id); + } + +}; +// Test: Locate keys by group +TEST_F (KmipClientIntegrationTest, LocateKeysByGroup) +{ + auto kmip = createKmipClient (); + std::string group_name = "test_locate_group_" + std::to_string (std::time (nullptr)); + std::vector expected_ids; + + try + { + // Create a few keys in the same unique group + for (int i = 0; i < 3; ++i) + { + auto key_id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX + "LocateByGroup_" + std::to_string (i), group_name); + expected_ids.push_back (key_id); + trackKeyForCleanup (key_id); + } + + // Locate by group + auto found_ids = kmip->client ().op_locate_by_group (group_name, KMIP_OBJTYPE_SYMMETRIC_KEY); + + // Verify all created keys are found + for (const auto &expected_id : expected_ids) + { + auto it = std::find (found_ids.begin (), found_ids.end (), expected_id); + EXPECT_NE (it, found_ids.end ()) << "Key " << expected_id << " not found in group " << group_name; + } + + std::cout << "Successfully located " << found_ids.size () << " objects in group: " << group_name << std::endl; + } + catch (ErrorException &e) + { + FAIL () << "Locate by group failed: " << e.what (); + } +} + +// Test: Create symmetric AES key +TEST_F (KmipClientIntegrationTest, CreateSymmetricAESKey) +{ + auto kmip = createKmipClient (); + + try + { + auto key_id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"CreateSymmetricAESKey", TEST_GROUP); + trackKeyForCleanup (key_id); + std::cout << "Created key with ID: " << key_id << std::endl; + } + catch (ErrorException &e) + { + FAIL () << "Failed to create key: " << e.what (); + } +} + +// Test: Create and Get key +TEST_F (KmipClientIntegrationTest, CreateAndGetKey) +{ + auto kmip = createKmipClient (); + kmipclient::id_t key_id; + // Create key + try + { + key_id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"CreateAndGetKey", TEST_GROUP); + trackKeyForCleanup (key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create key: " << e.what (); + } + + // Get key + try + { + auto key = kmip->client ().op_get_key (key_id); + EXPECT_FALSE (key.value ().empty ()); + EXPECT_EQ (key.value ().size (), 32); // 256 bits = 32 bytes + std::cout << "Retrieved key with " << key.value ().size () << " bytes" << std::endl; + } + catch (ErrorException &e) + { + FAIL () << "Failed to get key: " << e.what (); + } +} + +// Test: Create, Activate, and Get key +TEST_F (KmipClientIntegrationTest, CreateActivateAndGetKey) +{ + auto kmip = createKmipClient (); + kmipclient::id_t key_id; + // Create key + try + { + key_id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"CreateActivateAndGetKey", TEST_GROUP); + trackKeyForCleanup (key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create key: " << e.what (); + } + // Activate key + try + { + auto active_id = kmip->client ().op_activate (key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to activate key: " << e.what (); + } + + // Get key and it's state + try + { + auto get_result = kmip->client ().op_get_key (key_id); + ASSERT_FALSE (get_result.value ().empty ()) << "Failed to get activated key: " << key_id; + auto attrs = kmip->client ().op_get_attributes (key_id, {KMIP_ATTR_NAME_STATE}); + auto state = attrs[KMIP_ATTR_NAME_STATE]; + EXPECT_TRUE (state == "KMIP_STATE_ACTIVE") << "State is not ACTIVE for key: " << key_id; + std::cout << "Successfully activated and retrieved key: " << key_id << std::endl; + } + catch (ErrorException &e) + { + FAIL () << "Failed to activate key: " << e.what (); + } +} + +// Test: Register symmetric key +TEST_F (KmipClientIntegrationTest, RegisterSymmetricKey) +{ + auto kmip = createKmipClient (); + + // Create a test key value + std::vector key_value + = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; + try + { + auto key_id = kmip->client ().op_register_key (TESTING_NAME_PREFIX+"RegisterSymmetricKey", TEST_GROUP, + Key::aes_from_value (key_value)); + EXPECT_FALSE (key_id.empty ()); + std::cout << "Registered key with ID: " << key_id << std::endl; + trackKeyForCleanup (key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to register key: " << e.what (); + } +} + +// Test: Register secret data +TEST_F (KmipClientIntegrationTest, RegisterAndGetSecret) +{ + auto kmip = createKmipClient (); + kmipclient::id_t secret_id; + std::string secret_data = { 's', 'e', 'c', 'r', 'e', 't' }; + try + { + secret_id = kmip->client ().op_register_secret (TESTING_NAME_PREFIX+"a_secret", TEST_GROUP, secret_data, PASSWORD); + EXPECT_FALSE (secret_id.empty ()); + std::cout << "Registered secret with ID: " << secret_id << std::endl; + trackKeyForCleanup (secret_id); + } + catch (ErrorException &e) + { + std::cout << "Registered secret failed: " << e.what () << std::endl; + } + + try + { + auto retrieved_secret = kmip->client ().op_get_secret (secret_id); + EXPECT_EQ (retrieved_secret.value.size (), secret_data.size ()); + EXPECT_EQ (retrieved_secret.value, secret_data); + } + catch (ErrorException &e) + { + std::cout << "Get secret failed: " << e.what () << std::endl; + } +} + +// Test: Locate keys +TEST_F (KmipClientIntegrationTest, LocateKeys) +{ + auto kmip = createKmipClient (); + kmipclient::id_t key_id; + kmipclient::ids_t result; + kmipclient::name_t name = TESTING_NAME_PREFIX+"LocateKeys"; + // Create key + try + { + key_id = kmip->client ().op_create_aes_key (name, TEST_GROUP); + trackKeyForCleanup (key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create key: " << e.what (); + } + // Find by name + try + { + auto fkey_ids = kmip->client ().op_locate_by_name (name, KMIP_OBJTYPE_SYMMETRIC_KEY); + ASSERT_TRUE (fkey_ids.size () > 1); + EXPECT_EQ (fkey_ids[0], key_id); + std::cout << "Found " << fkey_ids.size () << " keys" << std::endl; + } + catch (ErrorException &e) + { + FAIL () << "Failed to find a key: " << e.what (); + } +} + +// Test: Get attributes +TEST_F (KmipClientIntegrationTest, CreateAndGetAttributes) +{ + auto kmip = createKmipClient (); + kmipclient::id_t key_id; + kmipclient::name_t name = TESTING_NAME_PREFIX+"CreateAndGetAttributes"; + // Create key + try + { + key_id = kmip->client ().op_create_aes_key (name, TEST_GROUP); + trackKeyForCleanup (key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create key: " << e.what (); + } + + // Get attributes + try + { + auto attr_result = kmip->client ().op_get_attributes (key_id, {KMIP_ATTR_NAME_NAME}); + attr_result.merge (kmip->client ().op_get_attributes (key_id, {KMIP_ATTR_NAME_GROUP})); + auto attr_name = attr_result[KMIP_ATTR_NAME_NAME]; + auto attr_group = attr_result[KMIP_ATTR_NAME_GROUP]; + std::cout << "Successfully retrieved attributes for key: " << key_id << std::endl; + EXPECT_EQ (name, attr_name); + EXPECT_EQ (TEST_GROUP, attr_group); + } + catch (ErrorException &e) + { + FAIL () << "Failed to get a key attribute: " << e.what (); + } +} + +// Test: Revoke key +TEST_F (KmipClientIntegrationTest, CreateAndRevokeKey) +{ + auto kmip = createKmipClient (); + + // Create and activate key + kmipclient::id_t key_id; + kmipclient::name_t name = TESTING_NAME_PREFIX+"CreateAndRevokeKey"; + // Create key + try + { + key_id = kmip->client ().op_create_aes_key (name, TEST_GROUP); + trackKeyForCleanup (key_id); + auto activate_result = kmip->client ().op_activate (key_id); + EXPECT_EQ (activate_result, key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create key: " << e.what (); + } + + // Revoke key + try + { + auto revoke_result = kmip->client ().op_revoke (key_id, UNSPECIFIED, "Test revocation", 0); + std::cout << "Successfully revoked key: " << key_id << std::endl; + } + catch (ErrorException &e) + { + FAIL () << "Failed to revoke key: " << e.what (); + } +} + +// Test: Full lifecycle - Create, Activate, Get, Revoke, Destroy +TEST_F (KmipClientIntegrationTest, FullKeyLifecycle) +{ + auto kmip = createKmipClient (); + try + { + // Create + auto key_id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"FullKeyLifecycle", TEST_GROUP); + std::cout << "1. Created key: " << key_id << std::endl; + + // Activate + auto activate_result = kmip->client ().op_activate (key_id); + ASSERT_FALSE (activate_result.empty ()) << "Activate failed: "; + std::cout << "2. Activated key" << std::endl; + + // Get + auto get_result = kmip->client ().op_get_key (key_id); + ASSERT_FALSE (get_result.value ().empty ()) << "Get failed: "; + std::cout << "3. Retrieved key" << std::endl; + + // Revoke + auto revoke_result = kmip->client ().op_revoke (key_id, UNSPECIFIED, "Test lifecycle", 0); + ASSERT_FALSE (revoke_result.empty ()) << "Revoke failed"; + std::cout << "4. Revoked key" << std::endl; + + // Destroy + auto destroy_result = kmip->client ().op_destroy (key_id); + ASSERT_TRUE (destroy_result == key_id) << "Destroy failed"; + std::cout << "5. Destroyed key" << std::endl; + } + catch (ErrorException &e) + { + FAIL () << "Failed full life cycle of key: " << e.what (); + } + // Don't track for cleanup since we already destroyed it +} + +// Test: Get non-existent key should fail +TEST_F (KmipClientIntegrationTest, GetNonExistentKey) +{ + auto kmip = createKmipClient (); + Key key; + std::string fake_id = "non-existent-key-id-12345"; + try + { + key = kmip->client ().op_get_key (fake_id); + } + catch (ErrorException &) + { + } + + ASSERT_TRUE (key.value ().empty ()) << "Should fail to get non-existent key"; +} + +// Test: Multiple keys creation +TEST_F (KmipClientIntegrationTest, CreateMultipleKeys) +{ + auto kmip = createKmipClient (); + + constexpr int num_keys = 3; + std::vector key_ids; + try + { + for (int i = 0; i < num_keys; ++i) + { + auto result = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"_CreateMultipleKeys_" + std::to_string (i), TEST_GROUP); + ASSERT_FALSE (result.empty ()) << "Failed to create key " << i; + + key_ids.push_back (result); + trackKeyForCleanup (result); + } + + EXPECT_EQ (key_ids.size (), num_keys); + } + catch (ErrorException &e) + { + FAIL () << "Multiple keys creation failed" << e.what (); + } + // Verify all keys are different + for (size_t i = 0; i < key_ids.size (); ++i) + { + for (size_t j = i + 1; j < key_ids.size (); ++j) + { + EXPECT_NE (key_ids[i], key_ids[j]) << "Keys should have unique IDs"; + } + } + + std::cout << "Successfully created " << num_keys << " unique keys" << std::endl; +} + +// Test: Destroying a key removes it (cannot be retrieved) +TEST_F (KmipClientIntegrationTest, DestroyKeyRemovesKey) +{ + auto kmip = createKmipClient (); + kmipclient::id_t key_id; + try + { + key_id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"DestroyKeyRemovesKey", TEST_GROUP); + ASSERT_FALSE (key_id.empty ()); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create key for destroy test: " << e.what (); + } + + // Destroy the key + try + { + auto destroy_result = kmip->client ().op_destroy (key_id); + ASSERT_EQ (destroy_result, key_id) << "Destroy did not return the expected id"; + } + catch (ErrorException &e) + { + FAIL () << "Failed to destroy key: " << e.what (); + } + + // Attempt to get the destroyed key - should not be retrievable + try + { + Key key = kmip->client ().op_get_key (key_id); + EXPECT_TRUE (key.value ().empty ()) << "Destroyed key should not be retrievable"; + } + catch (ErrorException &) + { + // Some servers respond with an error for non-existent objects; this is acceptable + SUCCEED (); + } +} + +// Test: Creating two keys with the same name should yield distinct IDs and both should be locatable +TEST_F (KmipClientIntegrationTest, CreateDuplicateNames) +{ + auto kmip = createKmipClient (); + kmipclient::name_t name = TESTING_NAME_PREFIX+"DuplicateNameTest"; + std::string id1, id2; + try + { + id1 = kmip->client ().op_create_aes_key (name, TEST_GROUP); + id2 = kmip->client ().op_create_aes_key (name, TEST_GROUP); + trackKeyForCleanup (id1); + trackKeyForCleanup (id2); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create duplicate-name keys: " << e.what (); + } + + ASSERT_FALSE (id1.empty ()); + ASSERT_FALSE (id2.empty ()); + EXPECT_NE (id1, id2) << "Duplicate name keys should have unique IDs"; + + try + { + auto found = kmip->client ().op_locate_by_name (name, KMIP_OBJTYPE_SYMMETRIC_KEY); + // Both created IDs should be present + auto it1 = std::find (found.begin (), found.end (), id1); + auto it2 = std::find (found.begin (), found.end (), id2); + EXPECT_NE (it1, found.end ()) << "First key not found by name"; + EXPECT_NE (it2, found.end ()) << "Second key not found by name"; + } + catch (ErrorException &e) + { + FAIL () << "Locate by name failed for duplicate names: " << e.what (); + } +} + +// Test: Revoke changes state to REVOKED +TEST_F (KmipClientIntegrationTest, RevokeChangesState) +{ + auto kmip = createKmipClient (); + kmipclient::id_t key_id; + try + { + key_id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"RevokeChangesState", TEST_GROUP); + trackKeyForCleanup (key_id); + auto activate_res = kmip->client ().op_activate (key_id); + EXPECT_EQ (activate_res, key_id); + } + catch (ErrorException &e) + { + FAIL () << "Failed to create/activate key for revoke test: " << e.what (); + } + + try + { + auto revoke_res = kmip->client ().op_revoke (key_id, UNSPECIFIED, "Test revoke state", 0); + EXPECT_FALSE (revoke_res.empty ()); + } + catch (ErrorException &e) + { + FAIL () << "Failed to revoke key: " << e.what (); + } + + try + { + auto attrs = kmip->client ().op_get_attributes (key_id, {KMIP_ATTR_NAME_STATE}); + auto state = attrs[KMIP_ATTR_NAME_STATE]; + EXPECT_TRUE (state == "KMIP_STATE_DEACTIVATED") << "Expected DEACTIVATED state, got: " << state; + } + catch (ErrorException &e) + { + FAIL () << "Failed to get attributes after revoke: " << e.what (); + } +} + +// Test: op_get_all_ids should include newly created keys of the requested object type +TEST_F (KmipClientIntegrationTest, GetAllIdsIncludesCreatedKeys) +{ + auto kmip = createKmipClient (); + std::vector created_ids; + try + { + for (int i = 0; i < 5; ++i) + { + auto id = kmip->client ().op_create_aes_key (TESTING_NAME_PREFIX+"GetAllIds_" + std::to_string (i), TEST_GROUP); + created_ids.push_back (id); + trackKeyForCleanup (id); + } + + auto all_ids = kmip->client ().op_all (KMIP_OBJTYPE_SYMMETRIC_KEY); + for (const auto &cid : created_ids) + { + auto it = std::find (all_ids.begin (), all_ids.end (), cid); + EXPECT_NE (it, all_ids.end ()) << "Created id " << cid << " not found in op_get_all_ids"; + } + } + catch (ErrorException &e) + { + FAIL () << "GetAllIdsIncludesCreatedKeys failed: " << e.what (); + } +} + +// Test: Register a symmetric key and verify its NAME attribute +TEST_F (KmipClientIntegrationTest, RegisterKeyAndGetAttributes) +{ + auto kmip = createKmipClient (); + std::string name = TESTING_NAME_PREFIX+"RegisterKeyAttrs"; + try + { + // Use a deterministic 256-bit (32 byte) key value for registration + std::vector key_value + = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }; + + auto key_id = kmip->client ().op_register_key (name, TEST_GROUP, Key::aes_from_value (key_value)); + EXPECT_FALSE (key_id.empty ()); + trackKeyForCleanup (key_id); + + auto attrs = kmip->client ().op_get_attributes (key_id, {KMIP_ATTR_NAME_NAME}); + auto attr_name = attrs[KMIP_ATTR_NAME_NAME]; + EXPECT_EQ (attr_name, name); + } + catch (ErrorException &e) + { + FAIL () << "RegisterKeyAndGetAttributes failed: " << e.what (); + } +} + +// Main function +int +main (int argc, char **argv) +{ + ::testing::InitGoogleTest (&argc, argv); + + // Disable test shuffling + ::testing::GTEST_FLAG (shuffle) = false; + + // Print configuration + auto &config = KmipTestConfig::getInstance (); + if (config.isConfigured ()) + { + std::cout << "KMIP Test Configuration:\n" + << " Server: " << config.kmip_addr << ":" << config.kmip_port << "\n" + << " Client CA: " << config.kmip_client_ca << "\n" + << " Client Key: " << config.kmip_client_key << "\n" + << " Server CA: " << config.kmip_server_ca << "\n" + << " Timeout: " << config.timeout_ms << "ms\n" + << std::endl; + } + return RUN_ALL_TESTS (); +} diff --git a/kmippp/CMakeLists.txt b/kmippp/CMakeLists.txt index 5f7183b..ad5dc8d 100644 --- a/kmippp/CMakeLists.txt +++ b/kmippp/CMakeLists.txt @@ -43,6 +43,7 @@ add_pp_demo(get_name) add_pp_demo(register) add_pp_demo(locate) add_pp_demo(all) +add_pp_demo(all_secrets) add_pp_demo(revoke) add_pp_demo(get_secret) add_pp_demo(register_secret) diff --git a/kmippp/demo_all_secrets.cpp b/kmippp/demo_all_secrets.cpp new file mode 100644 index 0000000..5b4532a --- /dev/null +++ b/kmippp/demo_all_secrets.cpp @@ -0,0 +1,41 @@ + + +#include "kmippp.h" +#include + +int +main (int argc, char **argv) +{ + + if (argc < 6) + { + std::cerr << "Usage: demo_locate " + " [group_name]" + << std::endl; + return -1; + } + + kmippp::context ctx (argv[1], argv[2], argv[3], argv[4], argv[5]); + // auto keys = ctx.op_all_secrets(); + const std::string group = argv[6]!=nullptr? argv[6] : "TestGroup"; + auto keys = ctx.op_locate_secrets_by_group (group); + if(keys.empty ()) + { + std::cerr << "No Secret Data found" << std::endl; + std::cerr << ctx.get_last_result () << std::endl; + return 1; + } + for (auto id : keys) + { + std::cout << "Key: " << id << " "; + auto secret = ctx.op_get_secret (id); + auto secret_name = ctx.op_get_name_attr (id); + std::cout << secret_name << " 0x"; + for (auto const &c : secret) + { + std::cout << std::hex << ((int)c); + } + std::cout << std::endl; + } + return 0; +} diff --git a/kmippp/kmippp.cpp b/kmippp/kmippp.cpp index 833a9e4..171940e 100644 --- a/kmippp/kmippp.cpp +++ b/kmippp/kmippp.cpp @@ -129,7 +129,7 @@ context::op_register (context::name_t name, name_t group, key_t key) { int attr_count; - group.empty()? attr_count = 4 : attr_count = 5; + group.empty() ? attr_count = 4 : attr_count = 5; Attribute a[attr_count]; for (int i = 0; i < attr_count; i++) @@ -380,6 +380,67 @@ context::op_locate_by_group (context::name_t group) return ret; } +context::ids_t +context::op_locate_secrets_by_group (context::name_t group) +{ + Attribute a[2]; + for (int i = 0; i < 2; i++) + { + kmip_init_attribute (&a[i]); + } + + object_type loctype = KMIP_OBJTYPE_SECRET_DATA; + a[0].type = KMIP_ATTR_OBJECT_TYPE; + a[0].value = &loctype; + + TextString ts2 = { 0, 0 }; + ts2.value = const_cast (group.c_str ()); + ts2.size = kmip_strnlen_s (ts2.value, 250); + a[1].type = KMIP_ATTR_OBJECT_GROUP; + a[1].value = &ts2; + + TemplateAttribute ta = { 0 }; + ta.attributes = a; + ta.attribute_count = ARRAY_LENGTH (a); + + int upto = 0; + int all = 1; // TMP + ids_t ret; + + LocateResponse locate_result; + + while (upto < all) + { + int result = kmip_bio_locate (bio_, a, 2, &locate_result, 16, upto); + + if (result != 0) + { + return {}; + } + + for (int i = 0; i < locate_result.ids_size; ++i) + { + ret.push_back (locate_result.ids[i]); + } + if (locate_result.located_items != 0) + { + all = locate_result.located_items; // shouldn't change after its != 1 + } + else + { + // Dummy server sometimes returns 0 for located_items + all += locate_result.ids_size; + if (locate_result.ids_size == 0) + { + --all; + } + } + upto += locate_result.ids_size; + } + + return ret; +} + context::ids_t context::op_all () { @@ -431,6 +492,57 @@ context::op_all () return ret; } +context::ids_t +context::op_all_secrets () +{ + Attribute a[1]; + for (int i = 0; i < 1; i++) + { + kmip_init_attribute (&a[i]); + } + + object_type loctype = KMIP_OBJTYPE_SECRET_DATA; + a[0].type = KMIP_ATTR_OBJECT_TYPE; + a[0].value = &loctype; + + LocateResponse locate_result; + + int upto = 0; + int all = 1; // TMP + ids_t ret; + + while (upto < all) + { + int result = kmip_bio_locate (bio_, a, 1, &locate_result, 16, upto); + + if (result != 0) + { + return {}; + } + + for (int i = 0; i < locate_result.ids_size; ++i) + { + ret.push_back (locate_result.ids[i]); + } + if (locate_result.located_items != 0) + { + all = locate_result.located_items; // shouldn't change after its != 1 + } + else + { + // Dummy server sometimes returns 0 for located_items + all += locate_result.ids_size; + if (locate_result.ids_size == 0) + { + --all; + } + } + upto += locate_result.ids_size; + } + + return ret; +} + bool context::op_revoke (id_t id, int reason, name_t message, time_t occurrence_time) { @@ -454,7 +566,7 @@ context::op_register_secret (name_t name, name_t group, name_t secret, int secre kmip_init_attribute (&a[i]); } - int32 mask = KMIP_CRYPTOMASK_ENCRYPT | KMIP_CRYPTOMASK_DECRYPT | KMIP_CRYPTOMASK_EXPORT; + int32 mask = KMIP_CRYPTOMASK_DERIVE_KEY | KMIP_CRYPTOMASK_EXPORT; a[0].type = KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK; a[0].value = &mask; diff --git a/kmippp/kmippp.h b/kmippp/kmippp.h index ac595c7..72031d2 100644 --- a/kmippp/kmippp.h +++ b/kmippp/kmippp.h @@ -55,12 +55,16 @@ class context ids_t op_locate_by_group (name_t group); + ids_t op_locate_secrets_by_group (name_t group); + bool op_destroy (id_t id); // KMIP::locate operation, retrieve all symmetric keys // note: name can be empty, and will retrieve all keys ids_t op_all (); + ids_t op_all_secrets (); + // KMIP::revoke operation, revoke activated or not activated key. Deactivates // active key bool op_revoke (id_t id, int reason, name_t message, time_t occurrence_time); diff --git a/libkmip/include/kmip.h b/libkmip/include/kmip.h index a39c293..3beacd6 100644 --- a/libkmip/include/kmip.h +++ b/libkmip/include/kmip.h @@ -12,1391 +12,16 @@ #include #include #include +#include // we have FILE* vars #include "libkmip_version.h" +#include "kmip_enums.h" +#include "kmip_structs.h" #ifdef __cplusplus extern "C" { #endif - - /* - Types and Constants - */ - - typedef int8_t int8; - typedef int16_t int16; - typedef int32_t int32; - typedef int64_t int64; - typedef int32 bool32; - - typedef uint8_t uint8; - typedef uint16_t uint16; - typedef uint32_t uint32; - typedef uint64_t uint64; - - typedef size_t memory_index; - -#ifdef intptr_t - typedef intptr_t intptr; -#else -typedef int64 intptr; -#endif - - typedef float real32; - typedef double real64; - -#define KMIP_TRUE (1) -#define KMIP_FALSE (0) - -#define KMIP_UNSET (-1) - -#define KMIP_MIN(a, b) (((a) < (b)) ? (a) : (b)) - -#define KMIP_OK (0) -#define KMIP_NOT_IMPLEMENTED (-1) -#define KMIP_ERROR_BUFFER_FULL (-2) -#define KMIP_ERROR_ATTR_UNSUPPORTED (-3) -#define KMIP_TAG_MISMATCH (-4) -#define KMIP_TYPE_MISMATCH (-5) -#define KMIP_LENGTH_MISMATCH (-6) -#define KMIP_PADDING_MISMATCH (-7) -#define KMIP_BOOLEAN_MISMATCH (-8) -#define KMIP_ENUM_MISMATCH (-9) -#define KMIP_ENUM_UNSUPPORTED (-10) -#define KMIP_INVALID_FOR_VERSION (-11) -#define KMIP_MEMORY_ALLOC_FAILED (-12) -#define KMIP_IO_FAILURE (-13) -#define KMIP_EXCEED_MAX_MESSAGE_SIZE (-14) -#define KMIP_MALFORMED_RESPONSE (-15) -#define KMIP_OBJECT_MISMATCH (-16) -#define KMIP_ARG_INVALID (-17) -#define KMIP_ERROR_BUFFER_UNDERFULL (-18) -#define KMIP_INVALID_ENCODING (-19) -#define KMIP_INVALID_FIELD (-20) -#define KMIP_INVALID_LENGTH (-21) - - /* - Enumerations - */ - - enum attestation_type - { - /* KMIP 1.2 */ - KMIP_ATTEST_TPM_QUOTE = 0x01, - KMIP_ATTEST_TCG_INTEGRITY_REPORT = 0x02, - KMIP_ATTEST_SAML_ASSERTION = 0x03 - }; - - enum attribute_type - { - /* KMIP 1.0 */ - KMIP_ATTR_UNIQUE_IDENTIFIER = 0, - KMIP_ATTR_NAME = 1, - KMIP_ATTR_OBJECT_TYPE = 2, - KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM = 3, - KMIP_ATTR_CRYPTOGRAPHIC_LENGTH = 4, - KMIP_ATTR_OPERATION_POLICY_NAME = 5, - KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK = 6, - KMIP_ATTR_STATE = 7, - KMIP_ATTR_APPLICATION_SPECIFIC_INFORMATION = 8, - KMIP_ATTR_OBJECT_GROUP = 9, - KMIP_ATTR_ACTIVATION_DATE = 10, - KMIP_ATTR_DEACTIVATION_DATE = 11, - KMIP_ATTR_PROCESS_START_DATE = 12, - KMIP_ATTR_PROTECT_STOP_DATE = 13, - KMIP_ATTR_CRYPTOGRAPHIC_PARAMETERS = 14 - }; - - enum batch_error_continuation_option - { - /* KMIP 1.0 */ - KMIP_BATCH_CONTINUE = 0x01, - KMIP_BATCH_STOP = 0x02, - KMIP_BATCH_UNDO = 0x03 - }; - - enum block_cipher_mode - { - /* KMIP 1.0 */ - KMIP_BLOCK_CBC = 0x01, - KMIP_BLOCK_ECB = 0x02, - KMIP_BLOCK_PCBC = 0x03, - KMIP_BLOCK_CFB = 0x04, - KMIP_BLOCK_OFB = 0x05, - KMIP_BLOCK_CTR = 0x06, - KMIP_BLOCK_CMAC = 0x07, - KMIP_BLOCK_CCM = 0x08, - KMIP_BLOCK_GCM = 0x09, - KMIP_BLOCK_CBC_MAC = 0x0A, - KMIP_BLOCK_XTS = 0x0B, - KMIP_BLOCK_AES_KEY_WRAP_PADDING = 0x0C, - KMIP_BLOCK_NIST_KEY_WRAP = 0x0D, - KMIP_BLOCK_X9102_AESKW = 0x0E, - KMIP_BLOCK_X9102_TDKW = 0x0F, - KMIP_BLOCK_X9102_AKW1 = 0x10, - KMIP_BLOCK_X9102_AKW2 = 0x11, - /* KMIP 1.4 */ - KMIP_BLOCK_AEAD = 0x12 - }; - - enum credential_type - { - /* KMIP 1.0 */ - KMIP_CRED_USERNAME_AND_PASSWORD = 0x01, - /* KMIP 1.1 */ - KMIP_CRED_DEVICE = 0x02, - /* KMIP 1.2 */ - KMIP_CRED_ATTESTATION = 0x03, - /* KMIP 2.0 */ - KMIP_CRED_ONE_TIME_PASSWORD = 0x04, - KMIP_CRED_HASHED_PASSWORD = 0x05, - KMIP_CRED_TICKET = 0x06 - }; - - enum cryptographic_algorithm - { - /* KMIP 1.0 */ - KMIP_CRYPTOALG_DES = 0x01, - KMIP_CRYPTOALG_TRIPLE_DES = 0x02, - KMIP_CRYPTOALG_AES = 0x03, - KMIP_CRYPTOALG_RSA = 0x04, - KMIP_CRYPTOALG_DSA = 0x05, - KMIP_CRYPTOALG_ECDSA = 0x06, - KMIP_CRYPTOALG_HMAC_SHA1 = 0x07, - KMIP_CRYPTOALG_HMAC_SHA224 = 0x08, - KMIP_CRYPTOALG_HMAC_SHA256 = 0x09, - KMIP_CRYPTOALG_HMAC_SHA384 = 0x0A, - KMIP_CRYPTOALG_HMAC_SHA512 = 0x0B, - KMIP_CRYPTOALG_HMAC_MD5 = 0x0C, - KMIP_CRYPTOALG_DH = 0x0D, - KMIP_CRYPTOALG_ECDH = 0x0E, - KMIP_CRYPTOALG_ECMQV = 0x0F, - KMIP_CRYPTOALG_BLOWFISH = 0x10, - KMIP_CRYPTOALG_CAMELLIA = 0x11, - KMIP_CRYPTOALG_CAST5 = 0x12, - KMIP_CRYPTOALG_IDEA = 0x13, - KMIP_CRYPTOALG_MARS = 0x14, - KMIP_CRYPTOALG_RC2 = 0x15, - KMIP_CRYPTOALG_RC4 = 0x16, - KMIP_CRYPTOALG_RC5 = 0x17, - KMIP_CRYPTOALG_SKIPJACK = 0x18, - KMIP_CRYPTOALG_TWOFISH = 0x19, - /* KMIP 1.2 */ - KMIP_CRYPTOALG_EC = 0x1A, - /* KMIP 1.3 */ - KMIP_CRYPTOALG_ONE_TIME_PAD = 0x1B, - /* KMIP 1.4 */ - KMIP_CRYPTOALG_CHACHA20 = 0x1C, - KMIP_CRYPTOALG_POLY1305 = 0x1D, - KMIP_CRYPTOALG_CHACHA20_POLY1305 = 0x1E, - KMIP_CRYPTOALG_SHA3_224 = 0x1F, - KMIP_CRYPTOALG_SHA3_256 = 0x20, - KMIP_CRYPTOALG_SHA3_384 = 0x21, - KMIP_CRYPTOALG_SHA3_512 = 0x22, - KMIP_CRYPTOALG_HMAC_SHA3_224 = 0x23, - KMIP_CRYPTOALG_HMAC_SHA3_256 = 0x24, - KMIP_CRYPTOALG_HMAC_SHA3_384 = 0x25, - KMIP_CRYPTOALG_HMAC_SHA3_512 = 0x26, - KMIP_CRYPTOALG_SHAKE_128 = 0x27, - KMIP_CRYPTOALG_SHAKE_256 = 0x28, - /* KMIP 2.0 */ - KMIP_CRYPTOALG_ARIA = 0x29, - KMIP_CRYPTOALG_SEED = 0x2A, - KMIP_CRYPTOALG_SM2 = 0x2B, - KMIP_CRYPTOALG_SM3 = 0x2C, - KMIP_CRYPTOALG_SM4 = 0x2D, - KMIP_CRYPTOALG_GOST_R_34_10_2012 = 0x2E, - KMIP_CRYPTOALG_GOST_R_34_11_2012 = 0x2F, - KMIP_CRYPTOALG_GOST_R_34_13_2015 = 0x30, - KMIP_CRYPTOALG_GOST_28147_89 = 0x31, - KMIP_CRYPTOALG_XMSS = 0x32, - KMIP_CRYPTOALG_SPHINCS_256 = 0x33, - KMIP_CRYPTOALG_MCELIECE = 0x34, - KMIP_CRYPTOALG_MCELIECE_6960119 = 0x35, - KMIP_CRYPTOALG_MCELIECE_8192128 = 0x36, - KMIP_CRYPTOALG_ED25519 = 0x37, - KMIP_CRYPTOALG_ED448 = 0x38 - }; - - enum cryptographic_usage_mask - { - /* KMIP 1.0 */ - KMIP_CRYPTOMASK_SIGN = 0x00000001, - KMIP_CRYPTOMASK_VERIFY = 0x00000002, - KMIP_CRYPTOMASK_ENCRYPT = 0x00000004, - KMIP_CRYPTOMASK_DECRYPT = 0x00000008, - KMIP_CRYPTOMASK_WRAP_KEY = 0x00000010, - KMIP_CRYPTOMASK_UNWRAP_KEY = 0x00000020, - KMIP_CRYPTOMASK_EXPORT = 0x00000040, - KMIP_CRYPTOMASK_MAC_GENERATE = 0x00000080, - KMIP_CRYPTOMASK_MAC_VERIFY = 0x00000100, - KMIP_CRYPTOMASK_DERIVE_KEY = 0x00000200, - KMIP_CRYPTOMASK_CONTENT_COMMITMENT = 0x00000400, - KMIP_CRYPTOMASK_KEY_AGREEMENT = 0x00000800, - KMIP_CRYPTOMASK_CERTIFICATE_SIGN = 0x00001000, - KMIP_CRYPTOMASK_CRL_SIGN = 0x00002000, - KMIP_CRYPTOMASK_GENERATE_CRYPTOGRAM = 0x00004000, - KMIP_CRYPTOMASK_VALIDATE_CRYPTOGRAM = 0x00008000, - KMIP_CRYPTOMASK_TRANSLATE_ENCRYPT = 0x00010000, - KMIP_CRYPTOMASK_TRANSLATE_DECRYPT = 0x00020000, - KMIP_CRYPTOMASK_TRANSLATE_WRAP = 0x00040000, - KMIP_CRYPTOMASK_TRANSLATE_UNWRAP = 0x00080000, - /* KMIP 2.0 */ - KMIP_CRYPTOMASK_AUTHENTICATE = 0x00100000, - KMIP_CRYPTOMASK_UNRESTRICTED = 0x00200000, - KMIP_CRYPTOMASK_FPE_ENCRYPT = 0x00400000, - KMIP_CRYPTOMASK_FPE_DECRYPT = 0x00800000 - }; - - enum digital_signature_algorithm - { - /* KMIP 1.1 */ - KMIP_DIGITAL_MD2_WITH_RSA = 0x01, - KMIP_DIGITAL_MD5_WITH_RSA = 0x02, - KMIP_DIGITAL_SHA1_WITH_RSA = 0x03, - KMIP_DIGITAL_SHA224_WITH_RSA = 0x04, - KMIP_DIGITAL_SHA256_WITH_RSA = 0x05, - KMIP_DIGITAL_SHA384_WITH_RSA = 0x06, - KMIP_DIGITAL_SHA512_WITH_RSA = 0x07, - KMIP_DIGITAL_RSASSA_PSS = 0x08, - KMIP_DIGITAL_DSA_WITH_SHA1 = 0x09, - KMIP_DIGITAL_DSA_WITH_SHA224 = 0x0A, - KMIP_DIGITAL_DSA_WITH_SHA256 = 0x0B, - KMIP_DIGITAL_ECDSA_WITH_SHA1 = 0x0C, - KMIP_DIGITAL_ECDSA_WITH_SHA224 = 0x0D, - KMIP_DIGITAL_ECDSA_WITH_SHA256 = 0x0E, - KMIP_DIGITAL_ECDSA_WITH_SHA384 = 0x0F, - KMIP_DIGITAL_ECDSA_WITH_SHA512 = 0x10, - /* KMIP 1.4 */ - KMIP_DIGITAL_SHA3_256_WITH_RSA = 0x11, - KMIP_DIGITAL_SHA3_384_WITH_RSA = 0x12, - KMIP_DIGITAL_SHA3_512_WITH_RSA = 0x13 - }; - - enum encoding_option - { - /* KMIP 1.1 */ - KMIP_ENCODE_NO_ENCODING = 0x01, - KMIP_ENCODE_TTLV_ENCODING = 0x02 - }; - - enum hashing_algorithm - { - /* KMIP 1.0 */ - KMIP_HASH_MD2 = 0x01, - KMIP_HASH_MD4 = 0x02, - KMIP_HASH_MD5 = 0x03, - KMIP_HASH_SHA1 = 0x04, - KMIP_HASH_SHA224 = 0x05, - KMIP_HASH_SHA256 = 0x06, - KMIP_HASH_SHA384 = 0x07, - KMIP_HASH_SHA512 = 0x08, - KMIP_HASH_RIPEMD160 = 0x09, - KMIP_HASH_TIGER = 0x0A, - KMIP_HASH_WHIRLPOOL = 0x0B, - /* KMIP 1.2 */ - KMIP_HASH_SHA512_224 = 0x0C, - KMIP_HASH_SHA512_256 = 0x0D, - /* KMIP 1.4 */ - KMIP_HASH_SHA3_224 = 0x0E, - KMIP_HASH_SHA3_256 = 0x0F, - KMIP_HASH_SHA3_384 = 0x10, - KMIP_HASH_SHA3_512 = 0x11 - }; - - enum key_compression_type - { - /* KMIP 1.0 */ - KMIP_KEYCOMP_EC_PUB_UNCOMPRESSED = 0x01, - KMIP_KEYCOMP_EC_PUB_X962_COMPRESSED_PRIME = 0x02, - KMIP_KEYCOMP_EC_PUB_X962_COMPRESSED_CHAR2 = 0x03, - KMIP_KEYCOMP_EC_PUB_X962_HYBRID = 0x04 - }; - - enum key_format_type - { - /* KMIP 1.0 */ - KMIP_KEYFORMAT_RAW = 0x01, - KMIP_KEYFORMAT_OPAQUE = 0x02, - KMIP_KEYFORMAT_PKCS1 = 0x03, - KMIP_KEYFORMAT_PKCS8 = 0x04, - KMIP_KEYFORMAT_X509 = 0x05, - KMIP_KEYFORMAT_EC_PRIVATE_KEY = 0x06, - KMIP_KEYFORMAT_TRANS_SYMMETRIC_KEY = 0x07, - KMIP_KEYFORMAT_TRANS_DSA_PRIVATE_KEY = 0x08, - KMIP_KEYFORMAT_TRANS_DSA_PUBLIC_KEY = 0x09, - KMIP_KEYFORMAT_TRANS_RSA_PRIVATE_KEY = 0x0A, - KMIP_KEYFORMAT_TRANS_RSA_PUBLIC_KEY = 0x0B, - KMIP_KEYFORMAT_TRANS_DH_PRIVATE_KEY = 0x0C, - KMIP_KEYFORMAT_TRANS_DH_PUBLIC_KEY = 0x0D, - KMIP_KEYFORMAT_TRANS_ECDSA_PRIVATE_KEY = 0x0E, /* Deprecated as of KMIP 1.3 */ - KMIP_KEYFORMAT_TRANS_ECDSA_PUBLIC_KEY = 0x0F, /* Deprecated as of KMIP 1.3 */ - KMIP_KEYFORMAT_TRANS_ECDH_PRIVATE_KEY = 0x10, /* Deprecated as of KMIP 1.3 */ - KMIP_KEYFORMAT_TRANS_ECDH_PUBLIC_KEY = 0x11, /* Deprecated as of KMIP 1.3 */ - KMIP_KEYFORMAT_TRANS_ECMQV_PRIVATE_KEY = 0x12, /* Deprecated as of KMIP 1.3 */ - KMIP_KEYFORMAT_TRANS_ECMQV_PUBLIC_KEY = 0x13, /* Deprecated as of KMIP 1.3 */ - /* KMIP 1.3 */ - KMIP_KEYFORMAT_TRANS_EC_PRIVATE_KEY = 0x14, - KMIP_KEYFORMAT_TRANS_EC_PUBLIC_KEY = 0x15, - /* KMIP 1.4 */ - KMIP_KEYFORMAT_PKCS12 = 0x16, - /* KMIP 2.0 */ - KMIP_KEYFORMAT_PKCS10 = 0x17 - }; - - enum key_role_type - { - /* KMIP 1.0 */ - KMIP_ROLE_BDK = 0x01, - KMIP_ROLE_CVK = 0x02, - KMIP_ROLE_DEK = 0x03, - KMIP_ROLE_MKAC = 0x04, - KMIP_ROLE_MKSMC = 0x05, - KMIP_ROLE_MKSMI = 0x06, - KMIP_ROLE_MKDAC = 0x07, - KMIP_ROLE_MKDN = 0x08, - KMIP_ROLE_MKCP = 0x09, - KMIP_ROLE_MKOTH = 0x0A, - KMIP_ROLE_KEK = 0x0B, - KMIP_ROLE_MAC16609 = 0x0C, - KMIP_ROLE_MAC97971 = 0x0D, - KMIP_ROLE_MAC97972 = 0x0E, - KMIP_ROLE_MAC97973 = 0x0F, - KMIP_ROLE_MAC97974 = 0x10, - KMIP_ROLE_MAC97975 = 0x11, - KMIP_ROLE_ZPK = 0x12, - KMIP_ROLE_PVKIBM = 0x13, - KMIP_ROLE_PVKPVV = 0x14, - KMIP_ROLE_PVKOTH = 0x15, - /* KMIP 1.4 */ - KMIP_ROLE_DUKPT = 0x16, - KMIP_ROLE_IV = 0x17, - KMIP_ROLE_TRKBK = 0x18 - }; - - enum key_wrap_type - { - /* KMIP 1.4 */ - KMIP_WRAPTYPE_NOT_WRAPPED = 0x01, - KMIP_WRAPTYPE_AS_REGISTERED = 0x02 - }; - - enum kmip_version - { - KMIP_1_0 = 0, - KMIP_1_1 = 1, - KMIP_1_2 = 2, - KMIP_1_3 = 3, - KMIP_1_4 = 4, - KMIP_2_0 = 5 - }; - - enum mask_generator - { - /* KMIP 1.4 */ - KMIP_MASKGEN_MGF1 = 0x01 - }; - - enum name_type - { - /* KMIP 1.0 */ - KMIP_NAME_UNINTERPRETED_TEXT_STRING = 0x01, - KMIP_NAME_URI = 0x02 - }; - - enum object_type - { - /* KMIP 1.0 */ - KMIP_OBJTYPE_CERTIFICATE = 0x01, - KMIP_OBJTYPE_SYMMETRIC_KEY = 0x02, - KMIP_OBJTYPE_PUBLIC_KEY = 0x03, - KMIP_OBJTYPE_PRIVATE_KEY = 0x04, - KMIP_OBJTYPE_SPLIT_KEY = 0x05, - KMIP_OBJTYPE_TEMPLATE = 0x06, /* Deprecated as of KMIP 1.3 */ - KMIP_OBJTYPE_SECRET_DATA = 0x07, - KMIP_OBJTYPE_OPAQUE_OBJECT = 0x08, - /* KMIP 1.2 */ - KMIP_OBJTYPE_PGP_KEY = 0x09, - /* KMIP 2.0 */ - KMIP_OBJTYPE_CERTIFICATE_REQUEST = 0x0A - }; - - enum operation - { - // # KMIP 1.0 - KMIP_OP_CREATE = 0x01, - KMIP_OP_CREATE_KEY_PAIR = 0x02, - KMIP_OP_REGISTER = 0x03, - KMIP_OP_REKEY = 0x04, - KMIP_OP_DERIVE_KEY = 0x05, - KMIP_OP_CERTIFY = 0x06, - KMIP_OP_RECERTIFY = 0x07, - KMIP_OP_LOCATE = 0x08, - KMIP_OP_CHECK = 0x09, - KMIP_OP_GET = 0x0A, - KMIP_OP_GET_ATTRIBUTES = 0x0B, - KMIP_OP_GET_ATTRIBUTE_LIST = 0x0C, - KMIP_OP_ADD_ATTRIBUTE = 0x0D, - KMIP_OP_MODIFY_ATTRIBUTE = 0x0E, - KMIP_OP_DELETE_ATTRIBUTE = 0x0F, - KMIP_OP_OBTAIN_LEASE = 0x10, - KMIP_OP_GET_USAGE_ALLOCATION = 0x11, - KMIP_OP_ACTIVATE = 0x12, - KMIP_OP_REVOKE = 0x13, - KMIP_OP_DESTROY = 0x14, - KMIP_OP_ARCHIVE = 0x15, - KMIP_OP_RECOVER = 0x16, - KMIP_OP_VALIDATE = 0x17, - KMIP_OP_QUERY = 0x18, - KMIP_OP_CANCEL = 0x19, - KMIP_OP_POLL = 0x1A, - KMIP_OP_NOTIFY = 0x1B, - KMIP_OP_PUT = 0x1C, - // # KMIP 1.1 - KMIP_OP_REKEY_KEY_PAIR = 0x1D, - KMIP_OP_DISCOVER_VERSIONS = 0x1E, - // # KMIP 1.2 - KMIP_OP_ENCRYPT = 0x1F, - KMIP_OP_DECRYPT = 0x20, - KMIP_OP_SIGN = 0x21, - KMIP_OP_SIGNATURE_VERIFY = 0x22, - KMIP_OP_MAC = 0x23, - KMIP_OP_MAC_VERIFY = 0x24, - KMIP_OP_RNG_RETRIEVE = 0x25, - KMIP_OP_RNG_SEED = 0x26, - KMIP_OP_HASH = 0x27, - KMIP_OP_CREATE_SPLIT_KEY = 0x28, - KMIP_OP_JOIN_SPLIT_KEY = 0x29, - // # KMIP 1.4 - KMIP_OP_IMPORT = 0x2A, - KMIP_OP_EXPORT = 0x2B, - // # KMIP 2.0 - KMIP_OP_LOG = 0x2C, - KMIP_OP_LOGIN = 0x2D, - KMIP_OP_LOGOUT = 0x2E, - KMIP_OP_DELEGATED_LOGIN = 0x2F, - KMIP_OP_ADJUST_ATTRIBUTE = 0x30, - KMIP_OP_SET_ATTRIBUTE = 0x31, - KMIP_OP_SET_ENDPOINT_ROLE = 0x32, - KMIP_OP_PKCS_11 = 0x33, - KMIP_OP_INTEROP = 0x34, - KMIP_OP_REPROVISION = 0x35, - }; - - enum padding_method - { - /* KMIP 1.0 */ - KMIP_PAD_NONE = 0x01, - KMIP_PAD_OAEP = 0x02, - KMIP_PAD_PKCS5 = 0x03, - KMIP_PAD_SSL3 = 0x04, - KMIP_PAD_ZEROS = 0x05, - KMIP_PAD_ANSI_X923 = 0x06, - KMIP_PAD_ISO_10126 = 0x07, - KMIP_PAD_PKCS1v15 = 0x08, - KMIP_PAD_X931 = 0x09, - KMIP_PAD_PSS = 0x0A - }; - - enum protection_storage_mask - { - /* KMIP 2.0 */ - KMIP_PROTECT_SOFTWARE = 0x00000001, - KMIP_PROTECT_HARDWARE = 0x00000002, - KMIP_PROTECT_ON_PROCESSOR = 0x00000004, - KMIP_PROTECT_ON_SYSTEM = 0x00000008, - KMIP_PROTECT_OFF_SYSTEM = 0x00000010, - KMIP_PROTECT_HYPERVISOR = 0x00000020, - KMIP_PROTECT_OPERATING_SYSTEM = 0x00000040, - KMIP_PROTECT_CONTAINER = 0x00000080, - KMIP_PROTECT_ON_PREMISES = 0x00000100, - KMIP_PROTECT_OFF_PREMISES = 0x00000200, - KMIP_PROTECT_SELF_MANAGED = 0x00000400, - KMIP_PROTECT_OUTSOURCED = 0x00000800, - KMIP_PROTECT_VALIDATED = 0x00001000, - KMIP_PROTECT_SAME_JURISDICTION = 0x00002000 - }; - - enum query_function - { - /* KMIP 1.0 */ - KMIP_QUERY_OPERATIONS = 0x0001, - KMIP_QUERY_OBJECTS = 0x0002, - KMIP_QUERY_SERVER_INFORMATION = 0x0003, - KMIP_QUERY_APPLICATION_NAMESPACES = 0x0004, - /* KMIP 1.1 */ - KMIP_QUERY_EXTENSION_LIST = 0x0005, - KMIP_QUERY_EXTENSION_MAP = 0x0006, - /* KMIP 1.2 */ - KMIP_QUERY_ATTESTATION_TYPES = 0x0007, - /* KMIP 1.3 */ - KMIP_QUERY_RNGS = 0x0008, - KMIP_QUERY_VALIDATIONS = 0x0009, - KMIP_QUERY_PROFILES = 0x000A, - KMIP_QUERY_CAPABILITIES = 0x000B, - KMIP_QUERY_CLIENT_REGISTRATION_METHODS = 0x000C, - /* KMIP 2.0 */ - KMIP_QUERY_DEFAULTS_INFORMATION = 0x000D, - KMIP_QUERY_STORAGE_PROTECTION_MASKS = 0x000E - }; - - enum result_reason - { - /* KMIP 1.0 */ - KMIP_REASON_GENERAL_FAILURE = 0x0100, - KMIP_REASON_ITEM_NOT_FOUND = 0x0001, - KMIP_REASON_RESPONSE_TOO_LARGE = 0x0002, - KMIP_REASON_AUTHENTICATION_NOT_SUCCESSFUL = 0x0003, - KMIP_REASON_INVALID_MESSAGE = 0x0004, - KMIP_REASON_OPERATION_NOT_SUPPORTED = 0x0005, - KMIP_REASON_MISSING_DATA = 0x0006, - KMIP_REASON_INVALID_FIELD = 0x0007, - KMIP_REASON_FEATURE_NOT_SUPPORTED = 0x0008, - KMIP_REASON_OPERATION_CANCELED_BY_REQUESTER = 0x0009, - KMIP_REASON_CRYPTOGRAPHIC_FAILURE = 0x000A, - KMIP_REASON_ILLEGAL_OPERATION = 0x000B, - KMIP_REASON_PERMISSION_DENIED = 0x000C, - KMIP_REASON_OBJECT_ARCHIVED = 0x000D, - KMIP_REASON_INDEX_OUT_OF_BOUNDS = 0x000E, - KMIP_REASON_APPLICATION_NAMESPACE_NOT_SUPPORTED = 0x000F, - KMIP_REASON_KEY_FORMAT_TYPE_NOT_SUPPORTED = 0x0010, - KMIP_REASON_KEY_COMPRESSION_TYPE_NOT_SUPPORTED = 0x0011, - /* KMIP 1.1 */ - KMIP_REASON_ENCODING_OPTION_FAILURE = 0x0012, - /* KMIP 1.2 */ - KMIP_REASON_KEY_VALUE_NOT_PRESENT = 0x0013, - KMIP_REASON_ATTESTATION_REQUIRED = 0x0014, - KMIP_REASON_ATTESTATION_FAILED = 0x0015, - /* KMIP 1.4 */ - KMIP_REASON_SENSITIVE = 0x0016, - KMIP_REASON_NOT_EXTRACTABLE = 0x0017, - KMIP_REASON_OBJECT_ALREADY_EXISTS = 0x0018, - /* KMIP 2.0 */ - KMIP_REASON_INVALID_TICKET = 0x0019, - KMIP_REASON_USAGE_LIMIT_EXCEEDED = 0x001A, - KMIP_REASON_NUMERIC_RANGE = 0x001B, - KMIP_REASON_INVALID_DATA_TYPE = 0x001C, - KMIP_REASON_READ_ONLY_ATTRIBUTE = 0x001D, - KMIP_REASON_MULTI_VALUED_ATTRIBUTE = 0x001E, - KMIP_REASON_UNSUPPORTED_ATTRIBUTE = 0x001F, - KMIP_REASON_ATTRIBUTE_INSTANCE_NOT_FOUND = 0x0020, - KMIP_REASON_ATTRIBUTE_NOT_FOUND = 0x0021, - KMIP_REASON_ATTRIBUTE_READ_ONLY = 0x0022, - KMIP_REASON_ATTRIBUTE_SINGLE_VALUED = 0x0023, - KMIP_REASON_BAD_CRYPTOGRAPHIC_PARAMETERS = 0x0024, - KMIP_REASON_BAD_PASSWORD = 0x0025, - KMIP_REASON_CODEC_ERROR = 0x0026, - /* Reserved = 0x0027, */ - KMIP_REASON_ILLEGAL_OBJECT_TYPE = 0x0028, - KMIP_REASON_INCOMPATIBLE_CRYPTOGRAPHIC_USAGE_MASK = 0x0029, - KMIP_REASON_INTERNAL_SERVER_ERROR = 0x002A, - KMIP_REASON_INVALID_ASYNCHRONOUS_CORRELATION_VALUE = 0x002B, - KMIP_REASON_INVALID_ATTRIBUTE = 0x002C, - KMIP_REASON_INVALID_ATTRIBUTE_VALUE = 0x002D, - KMIP_REASON_INVALID_CORRELATION_VALUE = 0x002E, - KMIP_REASON_INVALID_CSR = 0x002F, - KMIP_REASON_INVALID_OBJECT_TYPE = 0x0030, - /* Reserved = 0x0031, */ - KMIP_REASON_KEY_WRAP_TYPE_NOT_SUPPORTED = 0x0032, - /* Reserved = 0x0033, */ - KMIP_REASON_MISSING_INITIALIZATION_VECTOR = 0x0034, - KMIP_REASON_NON_UNIQUE_NAME_ATTRIBUTE = 0x0035, - KMIP_REASON_OBJECT_DESTROYED = 0x0036, - KMIP_REASON_OBJECT_NOT_FOUND = 0x0037, - /* Reserved = 0x0038, */ - KMIP_REASON_NOT_AUTHORISED = 0x0039, - KMIP_REASON_SERVER_LIMIT_EXCEEDED = 0x003A, - KMIP_REASON_UNKNOWN_ENUMERATION = 0x003B, - KMIP_REASON_UNKNOWN_MESSAGE_EXTENSION = 0x003C, - KMIP_REASON_UNKNOWN_TAG = 0x003D, - KMIP_REASON_UNSUPPORTED_CRYPTOGRAPHIC_PARAMETERS = 0x003E, - KMIP_REASON_UNSUPPORTED_PROTOCOL_VERSION = 0x003F, - KMIP_REASON_WRAPPING_OBJECT_ARCHIVED = 0x0040, - KMIP_REASON_WRAPPING_OBJECT_DESTROYED = 0x0041, - KMIP_REASON_WRAPPING_OBJECT_NOT_FOUND = 0x0042, - KMIP_REASON_WRONG_KEY_LIFECYCLE_STATE = 0x0043, - KMIP_REASON_PROTECTION_STORAGE_UNAVAILABLE = 0x0044, - KMIP_REASON_PKCS11_CODEC_ERROR = 0x0045, - KMIP_REASON_PKCS11_INVALID_FUNCTION = 0x0046, - KMIP_REASON_PKCS11_INVALID_INTERFACE = 0x0047, - KMIP_REASON_PRIVATE_PROTECTION_STORAGE_UNAVAILABLE = 0x0048, - KMIP_REASON_PUBLIC_PROTECTION_STORAGE_UNAVAILABLE = 0x0049 - }; - - enum result_status - { - /* KMIP 1.0 */ - KMIP_STATUS_SUCCESS = 0x00, - KMIP_STATUS_OPERATION_FAILED = 0x01, - KMIP_STATUS_OPERATION_PENDING = 0x02, - KMIP_STATUS_OPERATION_UNDONE = 0x03 - }; - - enum state - { - /* KMIP 1.0 */ - KMIP_STATE_PRE_ACTIVE = 0x01, - KMIP_STATE_ACTIVE = 0x02, - KMIP_STATE_DEACTIVATED = 0x03, - KMIP_STATE_COMPROMISED = 0x04, - KMIP_STATE_DESTROYED = 0x05, - KMIP_STATE_DESTROYED_COMPROMISED = 0x06 - }; - - enum tag - { - KMIP_TAG_TAG = 0x000000, - KMIP_TAG_TYPE = 0x000001, - KMIP_TAG_DEFAULT = 0x420000, - /* KMIP 1.0 */ - KMIP_TAG_ACTIVATION_DATE = 0x420001, - KMIP_TAG_APPLICATION_DATA = 0x420002, - KMIP_TAG_APPLICATION_NAMESPACE = 0x420003, - KMIP_TAG_APPLICATION_SPECIFIC_INFORMATION = 0x420004, - KMIP_TAG_ASYNCHRONOUS_CORRELATION_VALUE = 0x420006, - KMIP_TAG_ASYNCHRONOUS_INDICATOR = 0x420007, - KMIP_TAG_ATTRIBUTE = 0x420008, - KMIP_TAG_ATTRIBUTE_INDEX = 0x420009, - KMIP_TAG_ATTRIBUTE_NAME = 0x42000A, - KMIP_TAG_ATTRIBUTE_VALUE = 0x42000B, - KMIP_TAG_AUTHENTICATION = 0x42000C, - KMIP_TAG_BATCH_COUNT = 0x42000D, - KMIP_TAG_BATCH_ERROR_CONTINUATION_OPTION = 0x42000E, - KMIP_TAG_BATCH_ITEM = 0x42000F, - KMIP_TAG_BATCH_ORDER_OPTION = 0x420010, - KMIP_TAG_BLOCK_CIPHER_MODE = 0x420011, - KMIP_TAG_COMPROMISE_OCCURRANCE_DATE = 0x420021, - KMIP_TAG_CREDENTIAL = 0x420023, - KMIP_TAG_CREDENTIAL_TYPE = 0x420024, - KMIP_TAG_CREDENTIAL_VALUE = 0x420025, - KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM = 0x420028, - KMIP_TAG_CRYPTOGRAPHIC_LENGTH = 0x42002A, - KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS = 0x42002B, - KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK = 0x42002C, - KMIP_TAG_DEACTIVATION_DATE = 0x42002F, - KMIP_TAG_ENCRYPTION_KEY_INFORMATION = 0x420036, - KMIP_TAG_HASHING_ALGORITHM = 0x420038, - KMIP_TAG_IV_COUNTER_NONCE = 0x42003D, - KMIP_TAG_KEY = 0x42003F, - KMIP_TAG_KEY_BLOCK = 0x420040, - KMIP_TAG_KEY_COMPRESSION_TYPE = 0x420041, - KMIP_TAG_KEY_FORMAT_TYPE = 0x420042, - KMIP_TAG_KEY_MATERIAL = 0x420043, - KMIP_TAG_KEY_VALUE = 0x420045, - KMIP_TAG_KEY_WRAPPING_DATA = 0x420046, - KMIP_TAG_KEY_WRAPPING_SPECIFICATION = 0x420047, - KMIP_TAG_MAC_SIGNATURE = 0x42004D, - KMIP_TAG_MAC_SIGNATURE_KEY_INFORMATION = 0x42004E, - KMIP_TAG_MAXIMUM_ITEMS = 0x42004F, - KMIP_TAG_MAXIMUM_RESPONSE_SIZE = 0x420050, - KMIP_TAG_NAME = 0x420053, - KMIP_TAG_NAME_TYPE = 0x420054, - KMIP_TAG_NAME_VALUE = 0x420055, - KMIP_TAG_OBJECT_GROUP = 0x420056, - KMIP_TAG_OBJECT_TYPE = 0x420057, - KMIP_TAG_OPERATION = 0x42005C, - KMIP_TAG_OPERATION_POLICY_NAME = 0x42005D, - KMIP_TAG_PADDING_METHOD = 0x42005F, - KMIP_TAG_PRIVATE_KEY = 0x420064, - KMIP_TAG_PROCESS_START_DATE = 0x420067, - KMIP_TAG_PROTECT_STOP_DATE = 0x420068, - KMIP_TAG_PROTOCOL_VERSION = 0x420069, - KMIP_TAG_PROTOCOL_VERSION_MAJOR = 0x42006A, - KMIP_TAG_PROTOCOL_VERSION_MINOR = 0x42006B, - KMIP_TAG_PUBLIC_KEY = 0x42006D, - KMIP_TAG_QUERY_FUNCTION = 0x420074, - KMIP_TAG_REQUEST_HEADER = 0x420077, - KMIP_TAG_REQUEST_MESSAGE = 0x420078, - KMIP_TAG_REQUEST_PAYLOAD = 0x420079, - KMIP_TAG_RESPONSE_HEADER = 0x42007A, - KMIP_TAG_RESPONSE_MESSAGE = 0x42007B, - KMIP_TAG_RESPONSE_PAYLOAD = 0x42007C, - KMIP_TAG_RESULT_MESSAGE = 0x42007D, - KMIP_TAG_RESULT_REASON = 0x42007E, - KMIP_TAG_RESULT_STATUS = 0x42007F, - KMIP_TAG_REVOKATION_MESSAGE = 0x420080, - KMIP_TAG_REVOCATION_REASON = 0x420081, - KMIP_TAG_REVOCATION_REASON_CODE = 0x420082, - KMIP_TAG_KEY_ROLE_TYPE = 0x420083, - KMIP_TAG_SALT = 0x420084, - KMIP_TAG_SECRET_DATA = 0x420085, - KMIP_TAG_SECRET_DATA_TYPE = 0x420086, - KMIP_TAG_SERVER_INFORMATION = 0x420088, - KMIP_TAG_STATE = 0x42008D, - KMIP_TAG_STORAGE_STATUS_MASK = 0x42008E, - KMIP_TAG_SYMMETRIC_KEY = 0x42008F, - KMIP_TAG_TEMPLATE_ATTRIBUTE = 0x420091, - KMIP_TAG_TIME_STAMP = 0x420092, - KMIP_TAG_UNIQUE_BATCH_ITEM_ID = 0x420093, - KMIP_TAG_UNIQUE_IDENTIFIER = 0x420094, - KMIP_TAG_USERNAME = 0x420099, - KMIP_TAG_VENDOR_IDENTIFICATION = 0x42009D, - KMIP_TAG_WRAPPING_METHOD = 0x42009E, - KMIP_TAG_PASSWORD = 0x4200A1, - /* KMIP 1.1 */ - KMIP_TAG_DEVICE_IDENTIFIER = 0x4200A2, - KMIP_TAG_ENCODING_OPTION = 0x4200A3, - KMIP_TAG_MACHINE_IDENTIFIER = 0x4200A9, - KMIP_TAG_MEDIA_IDENTIFIER = 0x4200AA, - KMIP_TAG_NETWORK_IDENTIFIER = 0x4200AB, - KMIP_TAG_OBJECT_GROUP_MEMBER = 0x4200AC, - KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM = 0x4200AE, - KMIP_TAG_DEVICE_SERIAL_NUMBER = 0x4200B0, - /* KMIP 1.2 */ - KMIP_TAG_RANDOM_IV = 0x4200C5, - KMIP_TAG_ATTESTATION_TYPE = 0x4200C7, - KMIP_TAG_NONCE = 0x4200C8, - KMIP_TAG_NONCE_ID = 0x4200C9, - KMIP_TAG_NONCE_VALUE = 0x4200CA, - KMIP_TAG_ATTESTATION_MEASUREMENT = 0x4200CB, - KMIP_TAG_ATTESTATION_ASSERTION = 0x4200CC, - KMIP_TAG_IV_LENGTH = 0x4200CD, - KMIP_TAG_TAG_LENGTH = 0x4200CE, - KMIP_TAG_FIXED_FIELD_LENGTH = 0x4200CF, - KMIP_TAG_COUNTER_LENGTH = 0x4200D0, - KMIP_TAG_INITIAL_COUNTER_VALUE = 0x4200D1, - KMIP_TAG_INVOCATION_FIELD_LENGTH = 0x4200D2, - KMIP_TAG_ATTESTATION_CAPABLE_INDICATOR = 0x4200D3, - KMIP_TAG_OFFSET_ITEMS = 0x4200D4, - KMIP_TAG_LOCATED_ITEMS = 0x4200D5, - /* KMIP 1.4 */ - KMIP_TAG_KEY_WRAP_TYPE = 0x4200F8, - KMIP_TAG_SALT_LENGTH = 0x420100, - KMIP_TAG_MASK_GENERATOR = 0x420101, - KMIP_TAG_MASK_GENERATOR_HASHING_ALGORITHM = 0x420102, - KMIP_TAG_P_SOURCE = 0x420103, - KMIP_TAG_TRAILER_FIELD = 0x420104, - KMIP_TAG_CLIENT_CORRELATION_VALUE = 0x420105, - KMIP_TAG_SERVER_CORRELATION_VALUE = 0x420106, - /* KMIP 2.0 */ - KMIP_TAG_ATTRIBUTES = 0x420125, - KMIP_TAG_SERVER_NAME = 0x42012D, - KMIP_TAG_SERVER_SERIAL_NUMBER = 0x42012E, - KMIP_TAG_SERVER_VERSION = 0x42012F, - KMIP_TAG_SERVER_LOAD = 0x420130, - KMIP_TAG_PRODUCT_NAME = 0x420131, - KMIP_TAG_BUILD_LEVEL = 0x420132, - KMIP_TAG_BUILD_DATE = 0x420133, - KMIP_TAG_CLUSTER_INFO = 0x420134, - KMIP_TAG_ALTERNATE_FAILOVER_ENDPOINTS = 0x420135, - KMIP_TAG_EPHEMERAL = 0x420154, - KMIP_TAG_SERVER_HASHED_PASSWORD = 0x420155, - KMIP_TAG_PROTECTION_STORAGE_MASK = 0x42015E, - KMIP_TAG_PROTECTION_STORAGE_MASKS = 0x42015F, - KMIP_TAG_COMMON_PROTECTION_STORAGE_MASKS = 0x420163, - KMIP_TAG_PRIVATE_PROTECTION_STORAGE_MASKS = 0x420164, - KMIP_TAG_PUBLIC_PROTECTION_STORAGE_MASKS = 0x420165 - }; - - enum type - { - /* KMIP 1.0 */ - KMIP_TYPE_STRUCTURE = 0x01, - KMIP_TYPE_INTEGER = 0x02, - KMIP_TYPE_LONG_INTEGER = 0x03, - KMIP_TYPE_BIG_INTEGER = 0x04, - KMIP_TYPE_ENUMERATION = 0x05, - KMIP_TYPE_BOOLEAN = 0x06, - KMIP_TYPE_TEXT_STRING = 0x07, - KMIP_TYPE_BYTE_STRING = 0x08, - KMIP_TYPE_DATE_TIME = 0x09, - KMIP_TYPE_INTERVAL = 0x0A, - /* KMIP 2.0 */ - KMIP_TYPE_DATE_TIME_EXTENDED = 0x0B - }; - - enum wrapping_method - { - /* KMIP 1.0 */ - KMIP_WRAP_ENCRYPT = 0x01, - KMIP_WRAP_MAC_SIGN = 0x02, - KMIP_WRAP_ENCRYPT_MAC_SIGN = 0x03, - KMIP_WRAP_MAC_SIGN_ENCRYPT = 0x04, - KMIP_WRAP_TR31 = 0x05 - }; - - enum revocation_reason_type - { - /* KMIP 1.0 */ - UNSPECIFIED = 0x01, - KEY_COMPROMISE = 0x02, - CA_COMPROMISE = 0x03, - AFFILIATION_CHANGED = 0x04, - SUSPENDED = 0x05, - CESSATION_OF_OPERATION = 0x06, - PRIVILEDGE_WITHDRAWN = 0x07, - REVOCATION_EXTENSIONS = 0x80000000 - }; - - enum secret_data_type - { - /* KMIP 1.0 */ - PASSWORD = 0x01, - SEED = 0x02, - SECRET_DATA_EXTENSIONS = 0x80000000 - }; - - /* - Structures - */ - - typedef struct linked_list_item - { - struct linked_list_item *next; - struct linked_list_item *prev; - - void *data; - } LinkedListItem; - - typedef struct linked_list - { - LinkedListItem *head; - LinkedListItem *tail; - - size_t size; - } LinkedList; - - typedef struct text_string - { - char *value; - size_t size; - } TextString; - - typedef struct byte_string - { - uint8 *value; - size_t size; - } ByteString; - - typedef struct error_frame - { - char function[100]; - int line; - } ErrorFrame; - - typedef struct kmip - { - /* Encoding buffer */ - uint8 *buffer; - uint8 *index; - size_t size; - - /* KMIP message settings */ - enum kmip_version version; - int max_message_size; - LinkedList *credential_list; - - /* Error handling information */ - char *error_message; - size_t error_message_size; - /* TODO (ph) Switch the following to a LinkedList. */ - ErrorFrame errors[20]; - size_t error_frame_count; - struct error_frame *frame_index; - - /* Memory management function pointers */ - void *(*calloc_func) (void *state, size_t num, size_t size); - void *(*realloc_func) (void *state, void *ptr, size_t size); - void (*free_func) (void *state, void *ptr); - void *(*memcpy_func) (void *state, void *destination, const void *source, size_t size); - void *(*memset_func) (void *ptr, int value, size_t size); - void *state; - } KMIP; - - typedef struct application_specific_information - { - TextString *application_namespace; - TextString *application_data; - } ApplicationSpecificInformation; - - typedef struct attribute - { - enum attribute_type type; - int32 index; - void *value; - } Attribute; - - typedef struct attributes - { - LinkedList *attribute_list; - } Attributes; - - typedef struct name - { - struct text_string *value; - enum name_type type; - } Name; - - typedef struct template_attribute - { - /* TODO (ph) Change these to linked lists */ - Name *names; - size_t name_count; - Attribute *attributes; - size_t attribute_count; - } TemplateAttribute; - - typedef struct protocol_version - { - int32 major; - int32 minor; - } ProtocolVersion; - - typedef struct protection_storage_masks - { - /* KMIP 2.0 */ - LinkedList *masks; - } ProtectionStorageMasks; - - typedef struct cryptographic_parameters - { - /* KMIP 1.0 */ - enum block_cipher_mode block_cipher_mode; - enum padding_method padding_method; - enum hashing_algorithm hashing_algorithm; - enum key_role_type key_role_type; - /* KMIP 1.2 */ - enum digital_signature_algorithm digital_signature_algorithm; - enum cryptographic_algorithm cryptographic_algorithm; - bool32 random_iv; - int32 iv_length; - int32 tag_length; - int32 fixed_field_length; - int32 invocation_field_length; - int32 counter_length; - int32 initial_counter_value; - /* KMIP 1.4 */ - int32 salt_length; - enum mask_generator mask_generator; - enum hashing_algorithm mask_generator_hashing_algorithm; - ByteString *p_source; - int32 trailer_field; - } CryptographicParameters; - - typedef struct encryption_key_information - { - TextString *unique_identifier; - CryptographicParameters *cryptographic_parameters; - } EncryptionKeyInformation; - - typedef struct mac_signature_key_information - { - TextString *unique_identifier; - CryptographicParameters *cryptographic_parameters; - } MACSignatureKeyInformation; - - typedef struct key_wrapping_data - { - /* KMIP 1.0 */ - enum wrapping_method wrapping_method; - EncryptionKeyInformation *encryption_key_info; - MACSignatureKeyInformation *mac_signature_key_info; - ByteString *mac_signature; - ByteString *iv_counter_nonce; - /* KMIP 1.1 */ - enum encoding_option encoding_option; - } KeyWrappingData; - - typedef struct transparent_symmetric_key - { - ByteString *key; - } TransparentSymmetricKey; - - typedef struct key_value - { - void *key_material; - /* TODO (ph) Change this to a linked list */ - Attribute *attributes; - size_t attribute_count; - } KeyValue; - - typedef struct key_block - { - enum key_format_type key_format_type; - enum key_compression_type key_compression_type; - void *key_value; - enum type key_value_type; - enum cryptographic_algorithm cryptographic_algorithm; - int32 cryptographic_length; - KeyWrappingData *key_wrapping_data; - } KeyBlock; - - typedef struct symmetric_key - { - KeyBlock *key_block; - } SymmetricKey; - - typedef struct public_key - { - KeyBlock *key_block; - } PublicKey; - - typedef struct private_key - { - KeyBlock *key_block; - } PrivateKey; - - typedef struct key_wrapping_specification - { - /* KMIP 1.0 */ - enum wrapping_method wrapping_method; - EncryptionKeyInformation *encryption_key_info; - MACSignatureKeyInformation *mac_signature_key_info; - /* TODO (ph) Change this to a linked list */ - TextString *attribute_names; - size_t attribute_name_count; - /* KMIP 1.1 */ - enum encoding_option encoding_option; - } KeyWrappingSpecification; - - typedef struct nonce - { - ByteString *nonce_id; - ByteString *nonce_value; - } Nonce; - - typedef struct revocation_reason - { - enum revocation_reason_type reason; - TextString *message; - } RevocationReason; - - typedef struct secret_data - { - enum secret_data_type secret_data_type; - KeyBlock *key_block; - } SecretData; - - /* Operation Payloads */ - - typedef struct create_request_payload - { - /* KMIP 1.0 */ - enum object_type object_type; - TemplateAttribute *template_attribute; - /* KMIP 2.0 */ - Attributes *attributes; - ProtectionStorageMasks *protection_storage_masks; - } CreateRequestPayload; - - typedef struct register_request_payload - { - /* KMIP 1.0 */ - enum object_type object_type; // both - TemplateAttribute *template_attribute; - /* KMIP 2.0 */ - Attributes *attributes; - ProtectionStorageMasks *protection_storage_masks; - union - { - SymmetricKey symmetric_key; // both 1.0 and 2.0 - SecretData secret_data; - PublicKey public_key; - PrivateKey private_key; - } object; // both 1.0 and 2.0 - } RegisterRequestPayload; - - typedef struct register_response_payload - { - /* KMIP 1.0 */ - TextString *unique_identifier; - TemplateAttribute *template_attribute; - } RegisterResponsePayload; - - typedef struct create_response_payload - { - /* KMIP 1.0 */ - enum object_type object_type; - TextString *unique_identifier; - TemplateAttribute *template_attribute; - } CreateResponsePayload; - - typedef struct get_request_payload - { - /* KMIP 1.0 */ - TextString *unique_identifier; - enum key_format_type key_format_type; - enum key_compression_type key_compression_type; - KeyWrappingSpecification *key_wrapping_spec; - /* KMIP 1.4 */ - enum key_wrap_type key_wrap_type; - } GetRequestPayload; - - typedef struct get_response_payload - { - enum object_type object_type; - TextString *unique_identifier; - void *object; - } GetResponsePayload; - - typedef struct get_attribute_request_payload - { - /* KMIP 1.0 */ - TextString *unique_identifier; - TextString *attribute_name; - } GetAttributeRequestPayload; - - typedef struct get_attribute_response_payload - { - TextString *unique_identifier; - Attribute *attribute; - void *object; - } GetAttributeResponsePayload; - - typedef struct activate_request_payload - { - TextString *unique_identifier; - } ActivateRequestPayload; - - typedef struct activate_response_payload - { - TextString *unique_identifier; - } ActivateResponsePayload; - - typedef struct destroy_request_payload - { - TextString *unique_identifier; - } DestroyRequestPayload; - - typedef struct destroy_response_payload - { - TextString *unique_identifier; - } DestroyResponsePayload; - - typedef struct revoke_request_payload - { - TextString *unique_identifier; - RevocationReason *revocation_reason; - // optional time, see spec v 1.0 p 4.19 - int64 compromise_occurence_date; - } RevokeRequestPayload; - - typedef struct revoke_response_payload - { - TextString *unique_identifier; - } RevokeResponsePayload; - - /* Authentication Structures */ - - typedef struct credential - { - enum credential_type credential_type; - void *credential_value; - } Credential; - - typedef struct username_password_credential - { - TextString *username; - TextString *password; - } UsernamePasswordCredential; - - typedef struct device_credential - { - TextString *device_serial_number; - TextString *password; - TextString *device_identifier; - TextString *network_identifier; - TextString *machine_identifier; - TextString *media_identifier; - } DeviceCredential; - - typedef struct attestation_credential - { - Nonce *nonce; - enum attestation_type attestation_type; - ByteString *attestation_measurement; - ByteString *attestation_assertion; - } AttestationCredential; - - typedef struct authentication - { - /* NOTE (ph) KMIP 1.2+ supports multiple credentials here. */ - /* NOTE (ph) Polymorphism makes this tricky. Omitting for now. */ - /* TODO (ph) Credential structs are constant size, so no problem here. */ - /* TODO (ph) Change this to a linked list */ - Credential *credential; - } Authentication; - - /* Message Structures */ - - typedef struct request_header - { - /* KMIP 1.0 */ - ProtocolVersion *protocol_version; - int32 maximum_response_size; - bool32 asynchronous_indicator; - Authentication *authentication; - enum batch_error_continuation_option batch_error_continuation_option; - bool32 batch_order_option; - int64 time_stamp; - int32 batch_count; - /* KMIP 1.2 */ - bool32 attestation_capable_indicator; - enum attestation_type *attestation_types; - size_t attestation_type_count; - /* KMIP 1.4 */ - TextString *client_correlation_value; - TextString *server_correlation_value; - } RequestHeader; - - typedef struct response_header - { - /* KMIP 1.0 */ - ProtocolVersion *protocol_version; - int64 time_stamp; - int32 batch_count; - /* KMIP 1.2 */ - Nonce *nonce; - /* TODO (ph) Change this to a linked list */ - enum attestation_type *attestation_types; - size_t attestation_type_count; - /* KMIP 1.4 */ - TextString *client_correlation_value; - TextString *server_correlation_value; - /* KMIP 2.0 */ - ByteString *server_hashed_password; - } ResponseHeader; - - typedef struct request_batch_item - { - /* KMIP 1.0 */ - enum operation operation; - ByteString *unique_batch_item_id; - void *request_payload; - /* KMIP 2.0 */ - bool32 ephemeral; - /* NOTE (ph) Omitting the message extension field for now. */ - } RequestBatchItem; - - typedef struct response_batch_item - { - enum operation operation; - ByteString *unique_batch_item_id; - enum result_status result_status; - enum result_reason result_reason; - TextString *result_message; - ByteString *asynchronous_correlation_value; - void *response_payload; - /* NOTE (ph) Omitting the message extension field for now. */ - } ResponseBatchItem; - - typedef struct request_message - { - RequestHeader *request_header; - /* TODO (ph) Change this to a linked list */ - RequestBatchItem *batch_items; - size_t batch_count; - } RequestMessage; - - typedef struct response_message - { - ResponseHeader *response_header; - /* TODO (ph) Change this to a linked list */ - ResponseBatchItem *batch_items; - size_t batch_count; - } ResponseMessage; - - typedef struct functions - { - LinkedList *function_list; - } Functions; - - typedef struct operations - { - LinkedList *operation_list; - } Operations; - - typedef struct object_types - { - LinkedList *object_list; - } ObjectTypes; - - typedef struct alternative_endpoints - { - LinkedList *endpoint_list; - } AltEndpoints; - - typedef struct server_information - { - TextString *server_name; - TextString *server_serial_number; - TextString *server_version; - TextString *server_load; - TextString *product_name; - TextString *build_level; - TextString *build_date; - TextString *cluster_info; - AltEndpoints *alternative_failover_endpoints; - // Vendor-Specific Any, MAY be repeated - } ServerInformation; - - /* - typedef struct application_namespaces - { - LinkedList *app_namespace_list; - } ApplicationNamespaces; - */ - - typedef struct query_request_payload - { - Functions *functions; - } QueryRequestPayload; - - typedef struct query_response_payload - { - Operations *operations; // Specifies an Operation that is supported by the server. - ObjectTypes *objects; // Specifies a Managed Object Type that is supported - // by the server. - TextString *vendor_identification; // SHALL be returned if Query Server - // Information is requested. The Vendor - // Identification SHALL be a text string - // that uniquely identifies the vendor. - ServerInformation *server_information; // Contains vendor-specific information possibly - // be of interest to the client. - // ApplicationNamespaces* application_namespaces; // Specifies an - // Application Namespace supported by the server. Extension Information No, - // MAY be repeated // SHALL be returned if Query Extension List or Query - // Extension Map is requested and supported by the server. Attestation Type - // No, MAY be repeated // Specifies an Attestation Type that is supported - // by the server. RNG Parameters No, MAY be repeated // - // Specifies the RNG that is supported by the server. Profile Information - // No, MAY be repeated // Specifies the Profiles that are supported by the - // server. Validation Information No, MAY be repeated // Specifies - // the validations that are supported by the server. Capability Information - // No, MAY be repeated // Specifies the capabilities that are supported by - // the server. Client Registration Method No, MAY be repeated // - // Specifies a Client Registration Method that is supported by the server. - // Defaults Information No // Specifies the - // defaults that the server will use if the client omits them. Protection - // Storage Masks Yes // Specifies the list of - // Protection Storage Mask values supported by the server. A server MAY - // elect to provide an empty list in the Response if it is unable or - // unwilling to provide this information. - } QueryResponsePayload; - -#define MAX_QUERY_LEN 128 -#define MAX_QUERY_OPS 0x40 -#define MAX_QUERY_OBJS 0x20 - - typedef struct query_response - { - size_t operations_size; - int operations[MAX_QUERY_OPS]; - size_t objects_size; - int objects[MAX_QUERY_OBJS]; - char vendor_identification[MAX_QUERY_LEN]; - bool32 server_information_valid; - char server_name[MAX_QUERY_LEN]; - char server_serial_number[MAX_QUERY_LEN]; - char server_version[MAX_QUERY_LEN]; - char server_load[MAX_QUERY_LEN]; - char product_name[MAX_QUERY_LEN]; - char build_level[MAX_QUERY_LEN]; - char build_date[MAX_QUERY_LEN]; - char cluster_info[MAX_QUERY_LEN]; - } QueryResponse; - /* Macros */ @@ -1894,7 +519,7 @@ typedef int64 intptr; int kmip_encode_query_response_payload (KMIP *, const QueryResponsePayload *); int kmip_encode_revoke_request_payload (KMIP *, const RevokeRequestPayload *); int kmip_encode_revoke_response_payload (KMIP *, const RevokeResponsePayload *); - + int kmip_encode_get_attribute_list_request_payload (KMIP *ctx, const GetAttributeListRequestPayload *value); /* Decoding Functions */ @@ -1962,7 +587,7 @@ typedef int64 intptr; int kmip_decode_server_information (KMIP *ctx, ServerInformation *); int kmip_decode_revoke_request_payload (KMIP *, RevokeRequestPayload *); int kmip_decode_revoke_response_payload (KMIP *, RevokeResponsePayload *); - + int kmip_decode_get_attribute_list_response_payload (KMIP *ctx, GetAttributeListResponsePayload *value); #ifdef __cplusplus } #endif diff --git a/libkmip/include/kmip_bio.h b/libkmip/include/kmip_bio.h index acc96ff..fa47307 100644 --- a/libkmip/include/kmip_bio.h +++ b/libkmip/include/kmip_bio.h @@ -17,7 +17,7 @@ extern "C" { #endif - #define LAST_RESULT_MAX_MESSAGE_SIZE 512 //could be big with HasiCorp Vault + #define LAST_RESULT_MAX_MESSAGE_SIZE 512 /* could be big with HasiCorp Vault */ typedef struct query_response QueryResponse; typedef struct locate_response LocateResponse; diff --git a/libkmip/include/kmip_enums.h b/libkmip/include/kmip_enums.h new file mode 100644 index 0000000..7e9adbc --- /dev/null +++ b/libkmip/include/kmip_enums.h @@ -0,0 +1,848 @@ +/* Copyright (c) 2018 The Johns Hopkins University/Applied Physics Laboratory + * All Rights Reserved. + * + * This file is dual licensed under the terms of the Apache 2.0 License and + * the BSD 3-Clause License. See the LICENSE file in the root of this + * repository for more information. + */ + + +#ifndef KMIP_KMIP_ENUMS_H +#define KMIP_KMIP_ENUMS_H + + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define KMIP_MAX_MESSAGE_SIZE 8192 +#define KMIP_ERROR_MESSAGE_SIZE 200 + + /* + Types and Constants + */ + + typedef int8_t int8; + typedef int16_t int16; + typedef int32_t int32; + typedef int64_t int64; + typedef int32 bool32; + + typedef uint8_t uint8; + typedef uint16_t uint16; + typedef uint32_t uint32; + typedef uint64_t uint64; + + typedef size_t memory_index; + +#ifdef intptr_t + typedef intptr_t intptr; +#else +typedef int64 intptr; +#endif + + typedef float real32; + typedef double real64; + +#define KMIP_TRUE (1) +#define KMIP_FALSE (0) + +#define KMIP_UNSET (-1) + +#define KMIP_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define KMIP_OK (0) +#define KMIP_NOT_IMPLEMENTED (-1) +#define KMIP_ERROR_BUFFER_FULL (-2) +#define KMIP_ERROR_ATTR_UNSUPPORTED (-3) +#define KMIP_TAG_MISMATCH (-4) +#define KMIP_TYPE_MISMATCH (-5) +#define KMIP_LENGTH_MISMATCH (-6) +#define KMIP_PADDING_MISMATCH (-7) +#define KMIP_BOOLEAN_MISMATCH (-8) +#define KMIP_ENUM_MISMATCH (-9) +#define KMIP_ENUM_UNSUPPORTED (-10) +#define KMIP_INVALID_FOR_VERSION (-11) +#define KMIP_MEMORY_ALLOC_FAILED (-12) +#define KMIP_IO_FAILURE (-13) +#define KMIP_EXCEED_MAX_MESSAGE_SIZE (-14) +#define KMIP_MALFORMED_RESPONSE (-15) +#define KMIP_OBJECT_MISMATCH (-16) +#define KMIP_ARG_INVALID (-17) +#define KMIP_ERROR_BUFFER_UNDERFULL (-18) +#define KMIP_INVALID_ENCODING (-19) +#define KMIP_INVALID_FIELD (-20) +#define KMIP_INVALID_LENGTH (-21) + + /* + Enumerations + */ + + enum attestation_type + { + /* KMIP 1.2 */ + KMIP_ATTEST_TPM_QUOTE = 0x01, + KMIP_ATTEST_TCG_INTEGRITY_REPORT = 0x02, + KMIP_ATTEST_SAML_ASSERTION = 0x03 + }; + + enum attribute_type + { + /* KMIP 1.0 */ + KMIP_ATTR_UNIQUE_IDENTIFIER = 0, + KMIP_ATTR_NAME = 1, + KMIP_ATTR_OBJECT_TYPE = 2, + KMIP_ATTR_CRYPTOGRAPHIC_ALGORITHM = 3, + KMIP_ATTR_CRYPTOGRAPHIC_LENGTH = 4, + KMIP_ATTR_OPERATION_POLICY_NAME = 5, + KMIP_ATTR_CRYPTOGRAPHIC_USAGE_MASK = 6, + KMIP_ATTR_STATE = 7, + KMIP_ATTR_APPLICATION_SPECIFIC_INFORMATION = 8, + KMIP_ATTR_OBJECT_GROUP = 9, + KMIP_ATTR_ACTIVATION_DATE = 10, + KMIP_ATTR_DEACTIVATION_DATE = 11, + KMIP_ATTR_PROCESS_START_DATE = 12, + KMIP_ATTR_PROTECT_STOP_DATE = 13, + KMIP_ATTR_CRYPTOGRAPHIC_PARAMETERS = 14 + }; + + enum batch_error_continuation_option + { + /* KMIP 1.0 */ + KMIP_BATCH_CONTINUE = 0x01, + KMIP_BATCH_STOP = 0x02, + KMIP_BATCH_UNDO = 0x03 + }; + + enum block_cipher_mode + { + /* KMIP 1.0 */ + KMIP_BLOCK_CBC = 0x01, + KMIP_BLOCK_ECB = 0x02, + KMIP_BLOCK_PCBC = 0x03, + KMIP_BLOCK_CFB = 0x04, + KMIP_BLOCK_OFB = 0x05, + KMIP_BLOCK_CTR = 0x06, + KMIP_BLOCK_CMAC = 0x07, + KMIP_BLOCK_CCM = 0x08, + KMIP_BLOCK_GCM = 0x09, + KMIP_BLOCK_CBC_MAC = 0x0A, + KMIP_BLOCK_XTS = 0x0B, + KMIP_BLOCK_AES_KEY_WRAP_PADDING = 0x0C, + KMIP_BLOCK_NIST_KEY_WRAP = 0x0D, + KMIP_BLOCK_X9102_AESKW = 0x0E, + KMIP_BLOCK_X9102_TDKW = 0x0F, + KMIP_BLOCK_X9102_AKW1 = 0x10, + KMIP_BLOCK_X9102_AKW2 = 0x11, + /* KMIP 1.4 */ + KMIP_BLOCK_AEAD = 0x12 + }; + + enum credential_type + { + /* KMIP 1.0 */ + KMIP_CRED_USERNAME_AND_PASSWORD = 0x01, + /* KMIP 1.1 */ + KMIP_CRED_DEVICE = 0x02, + /* KMIP 1.2 */ + KMIP_CRED_ATTESTATION = 0x03, + /* KMIP 2.0 */ + KMIP_CRED_ONE_TIME_PASSWORD = 0x04, + KMIP_CRED_HASHED_PASSWORD = 0x05, + KMIP_CRED_TICKET = 0x06 + }; + + enum cryptographic_algorithm + { + KMIP_CRYPTOALG_UNSET = 0x00, + /* KMIP 1.0 */ + KMIP_CRYPTOALG_DES = 0x01, + KMIP_CRYPTOALG_TRIPLE_DES = 0x02, + KMIP_CRYPTOALG_AES = 0x03, + KMIP_CRYPTOALG_RSA = 0x04, + KMIP_CRYPTOALG_DSA = 0x05, + KMIP_CRYPTOALG_ECDSA = 0x06, + KMIP_CRYPTOALG_HMAC_SHA1 = 0x07, + KMIP_CRYPTOALG_HMAC_SHA224 = 0x08, + KMIP_CRYPTOALG_HMAC_SHA256 = 0x09, + KMIP_CRYPTOALG_HMAC_SHA384 = 0x0A, + KMIP_CRYPTOALG_HMAC_SHA512 = 0x0B, + KMIP_CRYPTOALG_HMAC_MD5 = 0x0C, + KMIP_CRYPTOALG_DH = 0x0D, + KMIP_CRYPTOALG_ECDH = 0x0E, + KMIP_CRYPTOALG_ECMQV = 0x0F, + KMIP_CRYPTOALG_BLOWFISH = 0x10, + KMIP_CRYPTOALG_CAMELLIA = 0x11, + KMIP_CRYPTOALG_CAST5 = 0x12, + KMIP_CRYPTOALG_IDEA = 0x13, + KMIP_CRYPTOALG_MARS = 0x14, + KMIP_CRYPTOALG_RC2 = 0x15, + KMIP_CRYPTOALG_RC4 = 0x16, + KMIP_CRYPTOALG_RC5 = 0x17, + KMIP_CRYPTOALG_SKIPJACK = 0x18, + KMIP_CRYPTOALG_TWOFISH = 0x19, + /* KMIP 1.2 */ + KMIP_CRYPTOALG_EC = 0x1A, + /* KMIP 1.3 */ + KMIP_CRYPTOALG_ONE_TIME_PAD = 0x1B, + /* KMIP 1.4 */ + KMIP_CRYPTOALG_CHACHA20 = 0x1C, + KMIP_CRYPTOALG_POLY1305 = 0x1D, + KMIP_CRYPTOALG_CHACHA20_POLY1305 = 0x1E, + KMIP_CRYPTOALG_SHA3_224 = 0x1F, + KMIP_CRYPTOALG_SHA3_256 = 0x20, + KMIP_CRYPTOALG_SHA3_384 = 0x21, + KMIP_CRYPTOALG_SHA3_512 = 0x22, + KMIP_CRYPTOALG_HMAC_SHA3_224 = 0x23, + KMIP_CRYPTOALG_HMAC_SHA3_256 = 0x24, + KMIP_CRYPTOALG_HMAC_SHA3_384 = 0x25, + KMIP_CRYPTOALG_HMAC_SHA3_512 = 0x26, + KMIP_CRYPTOALG_SHAKE_128 = 0x27, + KMIP_CRYPTOALG_SHAKE_256 = 0x28, + /* KMIP 2.0 */ + KMIP_CRYPTOALG_ARIA = 0x29, + KMIP_CRYPTOALG_SEED = 0x2A, + KMIP_CRYPTOALG_SM2 = 0x2B, + KMIP_CRYPTOALG_SM3 = 0x2C, + KMIP_CRYPTOALG_SM4 = 0x2D, + KMIP_CRYPTOALG_GOST_R_34_10_2012 = 0x2E, + KMIP_CRYPTOALG_GOST_R_34_11_2012 = 0x2F, + KMIP_CRYPTOALG_GOST_R_34_13_2015 = 0x30, + KMIP_CRYPTOALG_GOST_28147_89 = 0x31, + KMIP_CRYPTOALG_XMSS = 0x32, + KMIP_CRYPTOALG_SPHINCS_256 = 0x33, + KMIP_CRYPTOALG_MCELIECE = 0x34, + KMIP_CRYPTOALG_MCELIECE_6960119 = 0x35, + KMIP_CRYPTOALG_MCELIECE_8192128 = 0x36, + KMIP_CRYPTOALG_ED25519 = 0x37, + KMIP_CRYPTOALG_ED448 = 0x38 + }; + + enum cryptographic_usage_mask + { + KMIP_CRYPTOMASK_UNSET = 0x00000000, + /* KMIP 1.0 */ + KMIP_CRYPTOMASK_SIGN = 0x00000001, + KMIP_CRYPTOMASK_VERIFY = 0x00000002, + KMIP_CRYPTOMASK_ENCRYPT = 0x00000004, + KMIP_CRYPTOMASK_DECRYPT = 0x00000008, + KMIP_CRYPTOMASK_WRAP_KEY = 0x00000010, + KMIP_CRYPTOMASK_UNWRAP_KEY = 0x00000020, + KMIP_CRYPTOMASK_EXPORT = 0x00000040, + KMIP_CRYPTOMASK_MAC_GENERATE = 0x00000080, + KMIP_CRYPTOMASK_MAC_VERIFY = 0x00000100, + KMIP_CRYPTOMASK_DERIVE_KEY = 0x00000200, + KMIP_CRYPTOMASK_CONTENT_COMMITMENT = 0x00000400, + KMIP_CRYPTOMASK_KEY_AGREEMENT = 0x00000800, + KMIP_CRYPTOMASK_CERTIFICATE_SIGN = 0x00001000, + KMIP_CRYPTOMASK_CRL_SIGN = 0x00002000, + KMIP_CRYPTOMASK_GENERATE_CRYPTOGRAM = 0x00004000, + KMIP_CRYPTOMASK_VALIDATE_CRYPTOGRAM = 0x00008000, + KMIP_CRYPTOMASK_TRANSLATE_ENCRYPT = 0x00010000, + KMIP_CRYPTOMASK_TRANSLATE_DECRYPT = 0x00020000, + KMIP_CRYPTOMASK_TRANSLATE_WRAP = 0x00040000, + KMIP_CRYPTOMASK_TRANSLATE_UNWRAP = 0x00080000, + /* KMIP 2.0 */ + KMIP_CRYPTOMASK_AUTHENTICATE = 0x00100000, + KMIP_CRYPTOMASK_UNRESTRICTED = 0x00200000, + KMIP_CRYPTOMASK_FPE_ENCRYPT = 0x00400000, + KMIP_CRYPTOMASK_FPE_DECRYPT = 0x00800000 + }; + + enum digital_signature_algorithm + { + /* KMIP 1.1 */ + KMIP_DIGITAL_MD2_WITH_RSA = 0x01, + KMIP_DIGITAL_MD5_WITH_RSA = 0x02, + KMIP_DIGITAL_SHA1_WITH_RSA = 0x03, + KMIP_DIGITAL_SHA224_WITH_RSA = 0x04, + KMIP_DIGITAL_SHA256_WITH_RSA = 0x05, + KMIP_DIGITAL_SHA384_WITH_RSA = 0x06, + KMIP_DIGITAL_SHA512_WITH_RSA = 0x07, + KMIP_DIGITAL_RSASSA_PSS = 0x08, + KMIP_DIGITAL_DSA_WITH_SHA1 = 0x09, + KMIP_DIGITAL_DSA_WITH_SHA224 = 0x0A, + KMIP_DIGITAL_DSA_WITH_SHA256 = 0x0B, + KMIP_DIGITAL_ECDSA_WITH_SHA1 = 0x0C, + KMIP_DIGITAL_ECDSA_WITH_SHA224 = 0x0D, + KMIP_DIGITAL_ECDSA_WITH_SHA256 = 0x0E, + KMIP_DIGITAL_ECDSA_WITH_SHA384 = 0x0F, + KMIP_DIGITAL_ECDSA_WITH_SHA512 = 0x10, + /* KMIP 1.4 */ + KMIP_DIGITAL_SHA3_256_WITH_RSA = 0x11, + KMIP_DIGITAL_SHA3_384_WITH_RSA = 0x12, + KMIP_DIGITAL_SHA3_512_WITH_RSA = 0x13 + }; + + enum encoding_option + { + /* KMIP 1.1 */ + KMIP_ENCODE_NO_ENCODING = 0x01, + KMIP_ENCODE_TTLV_ENCODING = 0x02 + }; + + enum hashing_algorithm + { + /* KMIP 1.0 */ + KMIP_HASH_MD2 = 0x01, + KMIP_HASH_MD4 = 0x02, + KMIP_HASH_MD5 = 0x03, + KMIP_HASH_SHA1 = 0x04, + KMIP_HASH_SHA224 = 0x05, + KMIP_HASH_SHA256 = 0x06, + KMIP_HASH_SHA384 = 0x07, + KMIP_HASH_SHA512 = 0x08, + KMIP_HASH_RIPEMD160 = 0x09, + KMIP_HASH_TIGER = 0x0A, + KMIP_HASH_WHIRLPOOL = 0x0B, + /* KMIP 1.2 */ + KMIP_HASH_SHA512_224 = 0x0C, + KMIP_HASH_SHA512_256 = 0x0D, + /* KMIP 1.4 */ + KMIP_HASH_SHA3_224 = 0x0E, + KMIP_HASH_SHA3_256 = 0x0F, + KMIP_HASH_SHA3_384 = 0x10, + KMIP_HASH_SHA3_512 = 0x11 + }; + + enum key_compression_type + { + /* KMIP 1.0 */ + KMIP_KEYCOMP_EC_PUB_UNCOMPRESSED = 0x01, + KMIP_KEYCOMP_EC_PUB_X962_COMPRESSED_PRIME = 0x02, + KMIP_KEYCOMP_EC_PUB_X962_COMPRESSED_CHAR2 = 0x03, + KMIP_KEYCOMP_EC_PUB_X962_HYBRID = 0x04 + }; + + enum key_format_type + { + /* KMIP 1.0 */ + KMIP_KEYFORMAT_RAW = 0x01, + KMIP_KEYFORMAT_OPAQUE = 0x02, + KMIP_KEYFORMAT_PKCS1 = 0x03, + KMIP_KEYFORMAT_PKCS8 = 0x04, + KMIP_KEYFORMAT_X509 = 0x05, + KMIP_KEYFORMAT_EC_PRIVATE_KEY = 0x06, + KMIP_KEYFORMAT_TRANS_SYMMETRIC_KEY = 0x07, + KMIP_KEYFORMAT_TRANS_DSA_PRIVATE_KEY = 0x08, + KMIP_KEYFORMAT_TRANS_DSA_PUBLIC_KEY = 0x09, + KMIP_KEYFORMAT_TRANS_RSA_PRIVATE_KEY = 0x0A, + KMIP_KEYFORMAT_TRANS_RSA_PUBLIC_KEY = 0x0B, + KMIP_KEYFORMAT_TRANS_DH_PRIVATE_KEY = 0x0C, + KMIP_KEYFORMAT_TRANS_DH_PUBLIC_KEY = 0x0D, + KMIP_KEYFORMAT_TRANS_ECDSA_PRIVATE_KEY = 0x0E, /* Deprecated as of KMIP 1.3 */ + KMIP_KEYFORMAT_TRANS_ECDSA_PUBLIC_KEY = 0x0F, /* Deprecated as of KMIP 1.3 */ + KMIP_KEYFORMAT_TRANS_ECDH_PRIVATE_KEY = 0x10, /* Deprecated as of KMIP 1.3 */ + KMIP_KEYFORMAT_TRANS_ECDH_PUBLIC_KEY = 0x11, /* Deprecated as of KMIP 1.3 */ + KMIP_KEYFORMAT_TRANS_ECMQV_PRIVATE_KEY = 0x12, /* Deprecated as of KMIP 1.3 */ + KMIP_KEYFORMAT_TRANS_ECMQV_PUBLIC_KEY = 0x13, /* Deprecated as of KMIP 1.3 */ + /* KMIP 1.3 */ + KMIP_KEYFORMAT_TRANS_EC_PRIVATE_KEY = 0x14, + KMIP_KEYFORMAT_TRANS_EC_PUBLIC_KEY = 0x15, + /* KMIP 1.4 */ + KMIP_KEYFORMAT_PKCS12 = 0x16, + /* KMIP 2.0 */ + KMIP_KEYFORMAT_PKCS10 = 0x17 + }; + + enum key_role_type + { + /* KMIP 1.0 */ + KMIP_ROLE_BDK = 0x01, + KMIP_ROLE_CVK = 0x02, + KMIP_ROLE_DEK = 0x03, + KMIP_ROLE_MKAC = 0x04, + KMIP_ROLE_MKSMC = 0x05, + KMIP_ROLE_MKSMI = 0x06, + KMIP_ROLE_MKDAC = 0x07, + KMIP_ROLE_MKDN = 0x08, + KMIP_ROLE_MKCP = 0x09, + KMIP_ROLE_MKOTH = 0x0A, + KMIP_ROLE_KEK = 0x0B, + KMIP_ROLE_MAC16609 = 0x0C, + KMIP_ROLE_MAC97971 = 0x0D, + KMIP_ROLE_MAC97972 = 0x0E, + KMIP_ROLE_MAC97973 = 0x0F, + KMIP_ROLE_MAC97974 = 0x10, + KMIP_ROLE_MAC97975 = 0x11, + KMIP_ROLE_ZPK = 0x12, + KMIP_ROLE_PVKIBM = 0x13, + KMIP_ROLE_PVKPVV = 0x14, + KMIP_ROLE_PVKOTH = 0x15, + /* KMIP 1.4 */ + KMIP_ROLE_DUKPT = 0x16, + KMIP_ROLE_IV = 0x17, + KMIP_ROLE_TRKBK = 0x18 + }; + + enum key_wrap_type + { + /* KMIP 1.4 */ + KMIP_WRAPTYPE_NOT_WRAPPED = 0x01, + KMIP_WRAPTYPE_AS_REGISTERED = 0x02 + }; + + enum kmip_version + { + KMIP_1_0 = 0, + KMIP_1_1 = 1, + KMIP_1_2 = 2, + KMIP_1_3 = 3, + KMIP_1_4 = 4, + KMIP_2_0 = 5 + }; + + enum mask_generator + { + /* KMIP 1.4 */ + KMIP_MASKGEN_MGF1 = 0x01 + }; + + enum name_type + { + /* KMIP 1.0 */ + KMIP_NAME_UNINTERPRETED_TEXT_STRING = 0x01, + KMIP_NAME_URI = 0x02 + }; + + enum object_type + { + /* KMIP 1.0 */ + KMIP_OBJTYPE_CERTIFICATE = 0x01, + KMIP_OBJTYPE_SYMMETRIC_KEY = 0x02, + KMIP_OBJTYPE_PUBLIC_KEY = 0x03, + KMIP_OBJTYPE_PRIVATE_KEY = 0x04, + KMIP_OBJTYPE_SPLIT_KEY = 0x05, + KMIP_OBJTYPE_TEMPLATE = 0x06, /* Deprecated as of KMIP 1.3 */ + KMIP_OBJTYPE_SECRET_DATA = 0x07, + KMIP_OBJTYPE_OPAQUE_OBJECT = 0x08, + /* KMIP 1.2 */ + KMIP_OBJTYPE_PGP_KEY = 0x09, + /* KMIP 2.0 */ + KMIP_OBJTYPE_CERTIFICATE_REQUEST = 0x0A + }; + + enum operation + { + // # KMIP 1.0 + KMIP_OP_CREATE = 0x01, + KMIP_OP_CREATE_KEY_PAIR = 0x02, + KMIP_OP_REGISTER = 0x03, + KMIP_OP_REKEY = 0x04, + KMIP_OP_DERIVE_KEY = 0x05, + KMIP_OP_CERTIFY = 0x06, + KMIP_OP_RECERTIFY = 0x07, + KMIP_OP_LOCATE = 0x08, + KMIP_OP_CHECK = 0x09, + KMIP_OP_GET = 0x0A, + KMIP_OP_GET_ATTRIBUTES = 0x0B, + KMIP_OP_GET_ATTRIBUTE_LIST = 0x0C, + KMIP_OP_ADD_ATTRIBUTE = 0x0D, + KMIP_OP_MODIFY_ATTRIBUTE = 0x0E, + KMIP_OP_DELETE_ATTRIBUTE = 0x0F, + KMIP_OP_OBTAIN_LEASE = 0x10, + KMIP_OP_GET_USAGE_ALLOCATION = 0x11, + KMIP_OP_ACTIVATE = 0x12, + KMIP_OP_REVOKE = 0x13, + KMIP_OP_DESTROY = 0x14, + KMIP_OP_ARCHIVE = 0x15, + KMIP_OP_RECOVER = 0x16, + KMIP_OP_VALIDATE = 0x17, + KMIP_OP_QUERY = 0x18, + KMIP_OP_CANCEL = 0x19, + KMIP_OP_POLL = 0x1A, + KMIP_OP_NOTIFY = 0x1B, + KMIP_OP_PUT = 0x1C, + // # KMIP 1.1 + KMIP_OP_REKEY_KEY_PAIR = 0x1D, + KMIP_OP_DISCOVER_VERSIONS = 0x1E, + // # KMIP 1.2 + KMIP_OP_ENCRYPT = 0x1F, + KMIP_OP_DECRYPT = 0x20, + KMIP_OP_SIGN = 0x21, + KMIP_OP_SIGNATURE_VERIFY = 0x22, + KMIP_OP_MAC = 0x23, + KMIP_OP_MAC_VERIFY = 0x24, + KMIP_OP_RNG_RETRIEVE = 0x25, + KMIP_OP_RNG_SEED = 0x26, + KMIP_OP_HASH = 0x27, + KMIP_OP_CREATE_SPLIT_KEY = 0x28, + KMIP_OP_JOIN_SPLIT_KEY = 0x29, + // # KMIP 1.4 + KMIP_OP_IMPORT = 0x2A, + KMIP_OP_EXPORT = 0x2B, + // # KMIP 2.0 + KMIP_OP_LOG = 0x2C, + KMIP_OP_LOGIN = 0x2D, + KMIP_OP_LOGOUT = 0x2E, + KMIP_OP_DELEGATED_LOGIN = 0x2F, + KMIP_OP_ADJUST_ATTRIBUTE = 0x30, + KMIP_OP_SET_ATTRIBUTE = 0x31, + KMIP_OP_SET_ENDPOINT_ROLE = 0x32, + KMIP_OP_PKCS_11 = 0x33, + KMIP_OP_INTEROP = 0x34, + KMIP_OP_REPROVISION = 0x35, + }; + + enum padding_method + { + /* KMIP 1.0 */ + KMIP_PAD_NONE = 0x01, + KMIP_PAD_OAEP = 0x02, + KMIP_PAD_PKCS5 = 0x03, + KMIP_PAD_SSL3 = 0x04, + KMIP_PAD_ZEROS = 0x05, + KMIP_PAD_ANSI_X923 = 0x06, + KMIP_PAD_ISO_10126 = 0x07, + KMIP_PAD_PKCS1v15 = 0x08, + KMIP_PAD_X931 = 0x09, + KMIP_PAD_PSS = 0x0A + }; + + enum protection_storage_mask + { + /* KMIP 2.0 */ + KMIP_PROTECT_SOFTWARE = 0x00000001, + KMIP_PROTECT_HARDWARE = 0x00000002, + KMIP_PROTECT_ON_PROCESSOR = 0x00000004, + KMIP_PROTECT_ON_SYSTEM = 0x00000008, + KMIP_PROTECT_OFF_SYSTEM = 0x00000010, + KMIP_PROTECT_HYPERVISOR = 0x00000020, + KMIP_PROTECT_OPERATING_SYSTEM = 0x00000040, + KMIP_PROTECT_CONTAINER = 0x00000080, + KMIP_PROTECT_ON_PREMISES = 0x00000100, + KMIP_PROTECT_OFF_PREMISES = 0x00000200, + KMIP_PROTECT_SELF_MANAGED = 0x00000400, + KMIP_PROTECT_OUTSOURCED = 0x00000800, + KMIP_PROTECT_VALIDATED = 0x00001000, + KMIP_PROTECT_SAME_JURISDICTION = 0x00002000 + }; + + enum query_function + { + /* KMIP 1.0 */ + KMIP_QUERY_OPERATIONS = 0x0001, + KMIP_QUERY_OBJECTS = 0x0002, + KMIP_QUERY_SERVER_INFORMATION = 0x0003, + KMIP_QUERY_APPLICATION_NAMESPACES = 0x0004, + /* KMIP 1.1 */ + KMIP_QUERY_EXTENSION_LIST = 0x0005, + KMIP_QUERY_EXTENSION_MAP = 0x0006, + /* KMIP 1.2 */ + KMIP_QUERY_ATTESTATION_TYPES = 0x0007, + /* KMIP 1.3 */ + KMIP_QUERY_RNGS = 0x0008, + KMIP_QUERY_VALIDATIONS = 0x0009, + KMIP_QUERY_PROFILES = 0x000A, + KMIP_QUERY_CAPABILITIES = 0x000B, + KMIP_QUERY_CLIENT_REGISTRATION_METHODS = 0x000C, + /* KMIP 2.0 */ + KMIP_QUERY_DEFAULTS_INFORMATION = 0x000D, + KMIP_QUERY_STORAGE_PROTECTION_MASKS = 0x000E + }; + + enum result_reason + { + /* KMIP 1.0 */ + KMIP_REASON_GENERAL_FAILURE = 0x0100, + KMIP_REASON_ITEM_NOT_FOUND = 0x0001, + KMIP_REASON_RESPONSE_TOO_LARGE = 0x0002, + KMIP_REASON_AUTHENTICATION_NOT_SUCCESSFUL = 0x0003, + KMIP_REASON_INVALID_MESSAGE = 0x0004, + KMIP_REASON_OPERATION_NOT_SUPPORTED = 0x0005, + KMIP_REASON_MISSING_DATA = 0x0006, + KMIP_REASON_INVALID_FIELD = 0x0007, + KMIP_REASON_FEATURE_NOT_SUPPORTED = 0x0008, + KMIP_REASON_OPERATION_CANCELED_BY_REQUESTER = 0x0009, + KMIP_REASON_CRYPTOGRAPHIC_FAILURE = 0x000A, + KMIP_REASON_ILLEGAL_OPERATION = 0x000B, + KMIP_REASON_PERMISSION_DENIED = 0x000C, + KMIP_REASON_OBJECT_ARCHIVED = 0x000D, + KMIP_REASON_INDEX_OUT_OF_BOUNDS = 0x000E, + KMIP_REASON_APPLICATION_NAMESPACE_NOT_SUPPORTED = 0x000F, + KMIP_REASON_KEY_FORMAT_TYPE_NOT_SUPPORTED = 0x0010, + KMIP_REASON_KEY_COMPRESSION_TYPE_NOT_SUPPORTED = 0x0011, + /* KMIP 1.1 */ + KMIP_REASON_ENCODING_OPTION_FAILURE = 0x0012, + /* KMIP 1.2 */ + KMIP_REASON_KEY_VALUE_NOT_PRESENT = 0x0013, + KMIP_REASON_ATTESTATION_REQUIRED = 0x0014, + KMIP_REASON_ATTESTATION_FAILED = 0x0015, + /* KMIP 1.4 */ + KMIP_REASON_SENSITIVE = 0x0016, + KMIP_REASON_NOT_EXTRACTABLE = 0x0017, + KMIP_REASON_OBJECT_ALREADY_EXISTS = 0x0018, + /* KMIP 2.0 */ + KMIP_REASON_INVALID_TICKET = 0x0019, + KMIP_REASON_USAGE_LIMIT_EXCEEDED = 0x001A, + KMIP_REASON_NUMERIC_RANGE = 0x001B, + KMIP_REASON_INVALID_DATA_TYPE = 0x001C, + KMIP_REASON_READ_ONLY_ATTRIBUTE = 0x001D, + KMIP_REASON_MULTI_VALUED_ATTRIBUTE = 0x001E, + KMIP_REASON_UNSUPPORTED_ATTRIBUTE = 0x001F, + KMIP_REASON_ATTRIBUTE_INSTANCE_NOT_FOUND = 0x0020, + KMIP_REASON_ATTRIBUTE_NOT_FOUND = 0x0021, + KMIP_REASON_ATTRIBUTE_READ_ONLY = 0x0022, + KMIP_REASON_ATTRIBUTE_SINGLE_VALUED = 0x0023, + KMIP_REASON_BAD_CRYPTOGRAPHIC_PARAMETERS = 0x0024, + KMIP_REASON_BAD_PASSWORD = 0x0025, + KMIP_REASON_CODEC_ERROR = 0x0026, + /* Reserved = 0x0027, */ + KMIP_REASON_ILLEGAL_OBJECT_TYPE = 0x0028, + KMIP_REASON_INCOMPATIBLE_CRYPTOGRAPHIC_USAGE_MASK = 0x0029, + KMIP_REASON_INTERNAL_SERVER_ERROR = 0x002A, + KMIP_REASON_INVALID_ASYNCHRONOUS_CORRELATION_VALUE = 0x002B, + KMIP_REASON_INVALID_ATTRIBUTE = 0x002C, + KMIP_REASON_INVALID_ATTRIBUTE_VALUE = 0x002D, + KMIP_REASON_INVALID_CORRELATION_VALUE = 0x002E, + KMIP_REASON_INVALID_CSR = 0x002F, + KMIP_REASON_INVALID_OBJECT_TYPE = 0x0030, + /* Reserved = 0x0031, */ + KMIP_REASON_KEY_WRAP_TYPE_NOT_SUPPORTED = 0x0032, + /* Reserved = 0x0033, */ + KMIP_REASON_MISSING_INITIALIZATION_VECTOR = 0x0034, + KMIP_REASON_NON_UNIQUE_NAME_ATTRIBUTE = 0x0035, + KMIP_REASON_OBJECT_DESTROYED = 0x0036, + KMIP_REASON_OBJECT_NOT_FOUND = 0x0037, + /* Reserved = 0x0038, */ + KMIP_REASON_NOT_AUTHORISED = 0x0039, + KMIP_REASON_SERVER_LIMIT_EXCEEDED = 0x003A, + KMIP_REASON_UNKNOWN_ENUMERATION = 0x003B, + KMIP_REASON_UNKNOWN_MESSAGE_EXTENSION = 0x003C, + KMIP_REASON_UNKNOWN_TAG = 0x003D, + KMIP_REASON_UNSUPPORTED_CRYPTOGRAPHIC_PARAMETERS = 0x003E, + KMIP_REASON_UNSUPPORTED_PROTOCOL_VERSION = 0x003F, + KMIP_REASON_WRAPPING_OBJECT_ARCHIVED = 0x0040, + KMIP_REASON_WRAPPING_OBJECT_DESTROYED = 0x0041, + KMIP_REASON_WRAPPING_OBJECT_NOT_FOUND = 0x0042, + KMIP_REASON_WRONG_KEY_LIFECYCLE_STATE = 0x0043, + KMIP_REASON_PROTECTION_STORAGE_UNAVAILABLE = 0x0044, + KMIP_REASON_PKCS11_CODEC_ERROR = 0x0045, + KMIP_REASON_PKCS11_INVALID_FUNCTION = 0x0046, + KMIP_REASON_PKCS11_INVALID_INTERFACE = 0x0047, + KMIP_REASON_PRIVATE_PROTECTION_STORAGE_UNAVAILABLE = 0x0048, + KMIP_REASON_PUBLIC_PROTECTION_STORAGE_UNAVAILABLE = 0x0049 + }; + + enum result_status + { + /* KMIP 1.0 */ + KMIP_STATUS_SUCCESS = 0x00, + KMIP_STATUS_OPERATION_FAILED = 0x01, + KMIP_STATUS_OPERATION_PENDING = 0x02, + KMIP_STATUS_OPERATION_UNDONE = 0x03 + }; + + enum state + { + /* KMIP 1.0 */ + KMIP_STATE_PRE_ACTIVE = 0x01, + KMIP_STATE_ACTIVE = 0x02, + KMIP_STATE_DEACTIVATED = 0x03, + KMIP_STATE_COMPROMISED = 0x04, + KMIP_STATE_DESTROYED = 0x05, + KMIP_STATE_DESTROYED_COMPROMISED = 0x06 + }; + + enum tag + { + KMIP_TAG_TAG = 0x000000, + KMIP_TAG_TYPE = 0x000001, + KMIP_TAG_DEFAULT = 0x420000, + /* KMIP 1.0 */ + KMIP_TAG_ACTIVATION_DATE = 0x420001, + KMIP_TAG_APPLICATION_DATA = 0x420002, + KMIP_TAG_APPLICATION_NAMESPACE = 0x420003, + KMIP_TAG_APPLICATION_SPECIFIC_INFORMATION = 0x420004, + KMIP_TAG_ASYNCHRONOUS_CORRELATION_VALUE = 0x420006, + KMIP_TAG_ASYNCHRONOUS_INDICATOR = 0x420007, + KMIP_TAG_ATTRIBUTE = 0x420008, + KMIP_TAG_ATTRIBUTE_INDEX = 0x420009, + KMIP_TAG_ATTRIBUTE_NAME = 0x42000A, + KMIP_TAG_ATTRIBUTE_VALUE = 0x42000B, + KMIP_TAG_AUTHENTICATION = 0x42000C, + KMIP_TAG_BATCH_COUNT = 0x42000D, + KMIP_TAG_BATCH_ERROR_CONTINUATION_OPTION = 0x42000E, + KMIP_TAG_BATCH_ITEM = 0x42000F, + KMIP_TAG_BATCH_ORDER_OPTION = 0x420010, + KMIP_TAG_BLOCK_CIPHER_MODE = 0x420011, + KMIP_TAG_COMPROMISE_OCCURRANCE_DATE = 0x420021, + KMIP_TAG_CREDENTIAL = 0x420023, + KMIP_TAG_CREDENTIAL_TYPE = 0x420024, + KMIP_TAG_CREDENTIAL_VALUE = 0x420025, + KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM = 0x420028, + KMIP_TAG_CRYPTOGRAPHIC_LENGTH = 0x42002A, + KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS = 0x42002B, + KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK = 0x42002C, + KMIP_TAG_DEACTIVATION_DATE = 0x42002F, + KMIP_TAG_ENCRYPTION_KEY_INFORMATION = 0x420036, + KMIP_TAG_HASHING_ALGORITHM = 0x420038, + KMIP_TAG_IV_COUNTER_NONCE = 0x42003D, + KMIP_TAG_KEY = 0x42003F, + KMIP_TAG_KEY_BLOCK = 0x420040, + KMIP_TAG_KEY_COMPRESSION_TYPE = 0x420041, + KMIP_TAG_KEY_FORMAT_TYPE = 0x420042, + KMIP_TAG_KEY_MATERIAL = 0x420043, + KMIP_TAG_KEY_VALUE = 0x420045, + KMIP_TAG_KEY_WRAPPING_DATA = 0x420046, + KMIP_TAG_KEY_WRAPPING_SPECIFICATION = 0x420047, + KMIP_TAG_MAC_SIGNATURE = 0x42004D, + KMIP_TAG_MAC_SIGNATURE_KEY_INFORMATION = 0x42004E, + KMIP_TAG_MAXIMUM_ITEMS = 0x42004F, + KMIP_TAG_MAXIMUM_RESPONSE_SIZE = 0x420050, + KMIP_TAG_NAME = 0x420053, + KMIP_TAG_NAME_TYPE = 0x420054, + KMIP_TAG_NAME_VALUE = 0x420055, + KMIP_TAG_OBJECT_GROUP = 0x420056, + KMIP_TAG_OBJECT_TYPE = 0x420057, + KMIP_TAG_OPERATION = 0x42005C, + KMIP_TAG_OPERATION_POLICY_NAME = 0x42005D, + KMIP_TAG_PADDING_METHOD = 0x42005F, + KMIP_TAG_PRIVATE_KEY = 0x420064, + KMIP_TAG_PROCESS_START_DATE = 0x420067, + KMIP_TAG_PROTECT_STOP_DATE = 0x420068, + KMIP_TAG_PROTOCOL_VERSION = 0x420069, + KMIP_TAG_PROTOCOL_VERSION_MAJOR = 0x42006A, + KMIP_TAG_PROTOCOL_VERSION_MINOR = 0x42006B, + KMIP_TAG_PUBLIC_KEY = 0x42006D, + KMIP_TAG_QUERY_FUNCTION = 0x420074, + KMIP_TAG_REQUEST_HEADER = 0x420077, + KMIP_TAG_REQUEST_MESSAGE = 0x420078, + KMIP_TAG_REQUEST_PAYLOAD = 0x420079, + KMIP_TAG_RESPONSE_HEADER = 0x42007A, + KMIP_TAG_RESPONSE_MESSAGE = 0x42007B, + KMIP_TAG_RESPONSE_PAYLOAD = 0x42007C, + KMIP_TAG_RESULT_MESSAGE = 0x42007D, + KMIP_TAG_RESULT_REASON = 0x42007E, + KMIP_TAG_RESULT_STATUS = 0x42007F, + KMIP_TAG_REVOKATION_MESSAGE = 0x420080, + KMIP_TAG_REVOCATION_REASON = 0x420081, + KMIP_TAG_REVOCATION_REASON_CODE = 0x420082, + KMIP_TAG_KEY_ROLE_TYPE = 0x420083, + KMIP_TAG_SALT = 0x420084, + KMIP_TAG_SECRET_DATA = 0x420085, + KMIP_TAG_SECRET_DATA_TYPE = 0x420086, + KMIP_TAG_SERVER_INFORMATION = 0x420088, + KMIP_TAG_STATE = 0x42008D, + KMIP_TAG_STORAGE_STATUS_MASK = 0x42008E, + KMIP_TAG_SYMMETRIC_KEY = 0x42008F, + KMIP_TAG_TEMPLATE_ATTRIBUTE = 0x420091, + KMIP_TAG_TIME_STAMP = 0x420092, + KMIP_TAG_UNIQUE_BATCH_ITEM_ID = 0x420093, + KMIP_TAG_UNIQUE_IDENTIFIER = 0x420094, + KMIP_TAG_USERNAME = 0x420099, + KMIP_TAG_VENDOR_IDENTIFICATION = 0x42009D, + KMIP_TAG_WRAPPING_METHOD = 0x42009E, + KMIP_TAG_PASSWORD = 0x4200A1, + /* KMIP 1.1 */ + KMIP_TAG_DEVICE_IDENTIFIER = 0x4200A2, + KMIP_TAG_ENCODING_OPTION = 0x4200A3, + KMIP_TAG_MACHINE_IDENTIFIER = 0x4200A9, + KMIP_TAG_MEDIA_IDENTIFIER = 0x4200AA, + KMIP_TAG_NETWORK_IDENTIFIER = 0x4200AB, + KMIP_TAG_OBJECT_GROUP_MEMBER = 0x4200AC, + KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM = 0x4200AE, + KMIP_TAG_DEVICE_SERIAL_NUMBER = 0x4200B0, + /* KMIP 1.2 */ + KMIP_TAG_RANDOM_IV = 0x4200C5, + KMIP_TAG_ATTESTATION_TYPE = 0x4200C7, + KMIP_TAG_NONCE = 0x4200C8, + KMIP_TAG_NONCE_ID = 0x4200C9, + KMIP_TAG_NONCE_VALUE = 0x4200CA, + KMIP_TAG_ATTESTATION_MEASUREMENT = 0x4200CB, + KMIP_TAG_ATTESTATION_ASSERTION = 0x4200CC, + KMIP_TAG_IV_LENGTH = 0x4200CD, + KMIP_TAG_TAG_LENGTH = 0x4200CE, + KMIP_TAG_FIXED_FIELD_LENGTH = 0x4200CF, + KMIP_TAG_COUNTER_LENGTH = 0x4200D0, + KMIP_TAG_INITIAL_COUNTER_VALUE = 0x4200D1, + KMIP_TAG_INVOCATION_FIELD_LENGTH = 0x4200D2, + KMIP_TAG_ATTESTATION_CAPABLE_INDICATOR = 0x4200D3, + KMIP_TAG_OFFSET_ITEMS = 0x4200D4, + KMIP_TAG_LOCATED_ITEMS = 0x4200D5, + /* KMIP 1.4 */ + KMIP_TAG_KEY_WRAP_TYPE = 0x4200F8, + KMIP_TAG_SALT_LENGTH = 0x420100, + KMIP_TAG_MASK_GENERATOR = 0x420101, + KMIP_TAG_MASK_GENERATOR_HASHING_ALGORITHM = 0x420102, + KMIP_TAG_P_SOURCE = 0x420103, + KMIP_TAG_TRAILER_FIELD = 0x420104, + KMIP_TAG_CLIENT_CORRELATION_VALUE = 0x420105, + KMIP_TAG_SERVER_CORRELATION_VALUE = 0x420106, + /* KMIP 2.0 */ + KMIP_TAG_ATTRIBUTES = 0x420125, + KMIP_TAG_SERVER_NAME = 0x42012D, + KMIP_TAG_SERVER_SERIAL_NUMBER = 0x42012E, + KMIP_TAG_SERVER_VERSION = 0x42012F, + KMIP_TAG_SERVER_LOAD = 0x420130, + KMIP_TAG_PRODUCT_NAME = 0x420131, + KMIP_TAG_BUILD_LEVEL = 0x420132, + KMIP_TAG_BUILD_DATE = 0x420133, + KMIP_TAG_CLUSTER_INFO = 0x420134, + KMIP_TAG_ALTERNATE_FAILOVER_ENDPOINTS = 0x420135, + KMIP_TAG_EPHEMERAL = 0x420154, + KMIP_TAG_SERVER_HASHED_PASSWORD = 0x420155, + KMIP_TAG_PROTECTION_STORAGE_MASK = 0x42015E, + KMIP_TAG_PROTECTION_STORAGE_MASKS = 0x42015F, + KMIP_TAG_COMMON_PROTECTION_STORAGE_MASKS = 0x420163, + KMIP_TAG_PRIVATE_PROTECTION_STORAGE_MASKS = 0x420164, + KMIP_TAG_PUBLIC_PROTECTION_STORAGE_MASKS = 0x420165 + }; + + enum type + { + /* KMIP 1.0 */ + KMIP_TYPE_STRUCTURE = 0x01, + KMIP_TYPE_INTEGER = 0x02, + KMIP_TYPE_LONG_INTEGER = 0x03, + KMIP_TYPE_BIG_INTEGER = 0x04, + KMIP_TYPE_ENUMERATION = 0x05, + KMIP_TYPE_BOOLEAN = 0x06, + KMIP_TYPE_TEXT_STRING = 0x07, + KMIP_TYPE_BYTE_STRING = 0x08, + KMIP_TYPE_DATE_TIME = 0x09, + KMIP_TYPE_INTERVAL = 0x0A, + /* KMIP 2.0 */ + KMIP_TYPE_DATE_TIME_EXTENDED = 0x0B + }; + + enum wrapping_method + { + /* KMIP 1.0 */ + KMIP_WRAP_ENCRYPT = 0x01, + KMIP_WRAP_MAC_SIGN = 0x02, + KMIP_WRAP_ENCRYPT_MAC_SIGN = 0x03, + KMIP_WRAP_MAC_SIGN_ENCRYPT = 0x04, + KMIP_WRAP_TR31 = 0x05 + }; + + enum revocation_reason_type + { + /* KMIP 1.0 */ + UNSPECIFIED = 0x01, + KEY_COMPROMISE = 0x02, + CA_COMPROMISE = 0x03, + AFFILIATION_CHANGED = 0x04, + SUSPENDED = 0x05, + CESSATION_OF_OPERATION = 0x06, + PRIVILEDGE_WITHDRAWN = 0x07, + REVOCATION_EXTENSIONS = 0x80000000 + }; + + enum secret_data_type + { + /* KMIP 1.0 */ + PASSWORD = 0x01, + SEED = 0x02, + SECRET_DATA_EXTENSIONS = 0x80000000 + }; + + +#ifdef __cplusplus +} + +#endif +#endif // KMIP_KMIP_ENUMS_H diff --git a/libkmip/include/kmip_locate.h b/libkmip/include/kmip_locate.h index 83db246..dc4b9af 100644 --- a/libkmip/include/kmip_locate.h +++ b/libkmip/include/kmip_locate.h @@ -46,13 +46,13 @@ match. /* When the Object Group attribute and the Object Group Member flag are specified -in the request, and the value specified for Object Group Member is Group -Member Fresh, matching candidate objects SHALL be fresh objects from the +in the request, and the value specified for Object Group Member is Group +Member Fresh, matching candidate objects SHALL be fresh objects from the object group. If there are no more fresh objects in the group, the server MAY choose to generate a new object on-the-fly, based on server policy. If the value -specified for Object Group Member is Group Member Default, the server locates +specified for Object Group Member is Group Member Default, the server locates the default object as defined by server policy. diff --git a/libkmip/include/kmip_structs.h b/libkmip/include/kmip_structs.h new file mode 100644 index 0000000..55a1da1 --- /dev/null +++ b/libkmip/include/kmip_structs.h @@ -0,0 +1,592 @@ +/* Copyright (c) 2018 The Johns Hopkins University/Applied Physics Laboratory + * All Rights Reserved. + * + * This file is dual licensed under the terms of the Apache 2.0 License and + * the BSD 3-Clause License. See the LICENSE file in the root of this + * repository for more information. + */ + +#ifndef KMIP_KMIP_STRUCTS_H +#define KMIP_KMIP_STRUCTS_H +#ifdef __cplusplus +extern "C" +{ +#endif + + /* + Structures + */ + + typedef struct linked_list_item + { + struct linked_list_item *next; + struct linked_list_item *prev; + + void *data; + } LinkedListItem; + + typedef struct linked_list + { + LinkedListItem *head; + LinkedListItem *tail; + + size_t size; + } LinkedList; + + typedef struct text_string + { + char *value; + size_t size; + } TextString; + + typedef struct byte_string + { + uint8 *value; + size_t size; + } ByteString; + + typedef struct error_frame + { + char function[100]; + int line; + } ErrorFrame; + + typedef struct kmip + { + /* Encoding buffer */ + uint8 *buffer; + uint8 *index; + size_t size; + + /* KMIP message settings */ + enum kmip_version version; + int max_message_size; + LinkedList *credential_list; + + /* Error handling information */ + char *error_message; + size_t error_message_size; + /* TODO (ph) Switch the following to a LinkedList. */ + ErrorFrame errors[20]; + size_t error_frame_count; + struct error_frame *frame_index; + + /* Memory management function pointers */ + void *(*calloc_func) (void *state, size_t num, size_t size); + void *(*realloc_func) (void *state, void *ptr, size_t size); + void (*free_func) (void *state, void *ptr); + void *(*memcpy_func) (void *state, void *destination, const void *source, size_t size); + void *(*memset_func) (void *ptr, int value, size_t size); + void *state; + } KMIP; + + typedef struct application_specific_information + { + TextString *application_namespace; + TextString *application_data; + } ApplicationSpecificInformation; + + typedef struct attribute + { + enum attribute_type type; + int32 index; + void *value; + } Attribute; + + typedef struct attributes + { + LinkedList *attribute_list; + } Attributes; + + typedef struct name + { + struct text_string *value; + enum name_type type; + } Name; + + typedef struct template_attribute + { + /* TODO (ph) Change these to linked lists */ + Name *names; + size_t name_count; + Attribute *attributes; + size_t attribute_count; + } TemplateAttribute; + + typedef struct protocol_version + { + int32 major; + int32 minor; + } ProtocolVersion; + + typedef struct protection_storage_masks + { + /* KMIP 2.0 */ + LinkedList *masks; + } ProtectionStorageMasks; + + typedef struct cryptographic_parameters + { + /* KMIP 1.0 */ + enum block_cipher_mode block_cipher_mode; + enum padding_method padding_method; + enum hashing_algorithm hashing_algorithm; + enum key_role_type key_role_type; + /* KMIP 1.2 */ + enum digital_signature_algorithm digital_signature_algorithm; + enum cryptographic_algorithm cryptographic_algorithm; + bool32 random_iv; + int32 iv_length; + int32 tag_length; + int32 fixed_field_length; + int32 invocation_field_length; + int32 counter_length; + int32 initial_counter_value; + /* KMIP 1.4 */ + int32 salt_length; + enum mask_generator mask_generator; + enum hashing_algorithm mask_generator_hashing_algorithm; + ByteString *p_source; + int32 trailer_field; + } CryptographicParameters; + + typedef struct encryption_key_information + { + TextString *unique_identifier; + CryptographicParameters *cryptographic_parameters; + } EncryptionKeyInformation; + + typedef struct mac_signature_key_information + { + TextString *unique_identifier; + CryptographicParameters *cryptographic_parameters; + } MACSignatureKeyInformation; + + typedef struct key_wrapping_data + { + /* KMIP 1.0 */ + enum wrapping_method wrapping_method; + EncryptionKeyInformation *encryption_key_info; + MACSignatureKeyInformation *mac_signature_key_info; + ByteString *mac_signature; + ByteString *iv_counter_nonce; + /* KMIP 1.1 */ + enum encoding_option encoding_option; + } KeyWrappingData; + + typedef struct transparent_symmetric_key + { + ByteString *key; + } TransparentSymmetricKey; + + typedef struct key_value + { + void *key_material; + /* TODO (ph) Change this to a linked list */ + Attribute *attributes; + size_t attribute_count; + } KeyValue; + + typedef struct key_block + { + enum key_format_type key_format_type; + enum key_compression_type key_compression_type; + void *key_value; + enum type key_value_type; + enum cryptographic_algorithm cryptographic_algorithm; + int32 cryptographic_length; + KeyWrappingData *key_wrapping_data; + } KeyBlock; + + typedef struct symmetric_key + { + KeyBlock *key_block; + } SymmetricKey; + + typedef struct public_key + { + KeyBlock *key_block; + } PublicKey; + + typedef struct private_key + { + KeyBlock *key_block; + } PrivateKey; + + typedef struct key_wrapping_specification + { + /* KMIP 1.0 */ + enum wrapping_method wrapping_method; + EncryptionKeyInformation *encryption_key_info; + MACSignatureKeyInformation *mac_signature_key_info; + /* TODO (ph) Change this to a linked list */ + TextString *attribute_names; + size_t attribute_name_count; + /* KMIP 1.1 */ + enum encoding_option encoding_option; + } KeyWrappingSpecification; + + typedef struct nonce + { + ByteString *nonce_id; + ByteString *nonce_value; + } Nonce; + + typedef struct revocation_reason + { + enum revocation_reason_type reason; + TextString *message; + } RevocationReason; + + typedef struct secret_data + { + enum secret_data_type secret_data_type; + KeyBlock *key_block; + } SecretData; + + /* Operation Payloads */ + + typedef struct create_request_payload + { + /* KMIP 1.0 */ + enum object_type object_type; + TemplateAttribute *template_attribute; + /* KMIP 2.0 */ + Attributes *attributes; + ProtectionStorageMasks *protection_storage_masks; + } CreateRequestPayload; + + typedef struct register_request_payload + { + /* KMIP 1.0 */ + enum object_type object_type; // both + TemplateAttribute *template_attribute; + /* KMIP 2.0 */ + Attributes *attributes; + ProtectionStorageMasks *protection_storage_masks; + union + { + SymmetricKey symmetric_key; // both 1.0 and 2.0 + SecretData secret_data; + PublicKey public_key; + PrivateKey private_key; + } object; // both 1.0 and 2.0 + } RegisterRequestPayload; + + typedef struct register_response_payload + { + /* KMIP 1.0 */ + TextString *unique_identifier; + TemplateAttribute *template_attribute; + } RegisterResponsePayload; + + typedef struct create_response_payload + { + /* KMIP 1.0 */ + enum object_type object_type; + TextString *unique_identifier; + TemplateAttribute *template_attribute; + } CreateResponsePayload; + + typedef struct get_request_payload + { + /* KMIP 1.0 */ + TextString *unique_identifier; + enum key_format_type key_format_type; + enum key_compression_type key_compression_type; + KeyWrappingSpecification *key_wrapping_spec; + /* KMIP 1.4 */ + enum key_wrap_type key_wrap_type; + } GetRequestPayload; + + typedef struct get_response_payload + { + enum object_type object_type; + TextString *unique_identifier; + void *object; + } GetResponsePayload; + + typedef struct get_attribute_request_payload + { + /* KMIP 1.0 */ + TextString *unique_identifier; + TextString *attribute_name; + } GetAttributeRequestPayload; + + typedef struct get_attribute_response_payload + { + TextString *unique_identifier; + Attribute *attribute; + void *object; + } GetAttributeResponsePayload; + + typedef struct get_attribute_list_request_payload + { + TextString *unique_identifier; + } GetAttributeListRequestPayload; + + typedef struct get_attribute_list_response_payload + { + TextString *unique_identifier; + TextString *attribute_name; + } GetAttributeListResponsePayload; + + typedef struct activate_request_payload + { + TextString *unique_identifier; + } ActivateRequestPayload; + + typedef struct activate_response_payload + { + TextString *unique_identifier; + } ActivateResponsePayload; + + typedef struct destroy_request_payload + { + TextString *unique_identifier; + } DestroyRequestPayload; + + typedef struct destroy_response_payload + { + TextString *unique_identifier; + } DestroyResponsePayload; + + typedef struct revoke_request_payload + { + TextString *unique_identifier; + RevocationReason *revocation_reason; + // optional time, see spec v 1.0 p 4.19 + int64 compromise_occurence_date; + } RevokeRequestPayload; + + typedef struct revoke_response_payload + { + TextString *unique_identifier; + } RevokeResponsePayload; + + /* Authentication Structures */ + + typedef struct credential + { + enum credential_type credential_type; + void *credential_value; + } Credential; + + typedef struct username_password_credential + { + TextString *username; + TextString *password; + } UsernamePasswordCredential; + + typedef struct device_credential + { + TextString *device_serial_number; + TextString *password; + TextString *device_identifier; + TextString *network_identifier; + TextString *machine_identifier; + TextString *media_identifier; + } DeviceCredential; + + typedef struct attestation_credential + { + Nonce *nonce; + enum attestation_type attestation_type; + ByteString *attestation_measurement; + ByteString *attestation_assertion; + } AttestationCredential; + + typedef struct authentication + { + /* NOTE (ph) KMIP 1.2+ supports multiple credentials here. */ + /* NOTE (ph) Polymorphism makes this tricky. Omitting for now. */ + /* TODO (ph) Credential structs are constant size, so no problem here. */ + /* TODO (ph) Change this to a linked list */ + Credential *credential; + } Authentication; + + /* Message Structures */ + + typedef struct request_header + { + /* KMIP 1.0 */ + ProtocolVersion *protocol_version; + int32 maximum_response_size; + bool32 asynchronous_indicator; + Authentication *authentication; + enum batch_error_continuation_option batch_error_continuation_option; + bool32 batch_order_option; + int64 time_stamp; + int32 batch_count; + /* KMIP 1.2 */ + bool32 attestation_capable_indicator; + enum attestation_type *attestation_types; + size_t attestation_type_count; + /* KMIP 1.4 */ + TextString *client_correlation_value; + TextString *server_correlation_value; + } RequestHeader; + + typedef struct response_header + { + /* KMIP 1.0 */ + ProtocolVersion *protocol_version; + int64 time_stamp; + int32 batch_count; + /* KMIP 1.2 */ + Nonce *nonce; + /* TODO (ph) Change this to a linked list */ + enum attestation_type *attestation_types; + size_t attestation_type_count; + /* KMIP 1.4 */ + TextString *client_correlation_value; + TextString *server_correlation_value; + /* KMIP 2.0 */ + ByteString *server_hashed_password; + } ResponseHeader; + + typedef struct request_batch_item + { + /* KMIP 1.0 */ + enum operation operation; + ByteString *unique_batch_item_id; + void *request_payload; + /* KMIP 2.0 */ + bool32 ephemeral; + /* NOTE (ph) Omitting the message extension field for now. */ + } RequestBatchItem; + + typedef struct response_batch_item + { + enum operation operation; + ByteString *unique_batch_item_id; + enum result_status result_status; + enum result_reason result_reason; + TextString *result_message; + ByteString *asynchronous_correlation_value; + void *response_payload; + /* NOTE (ph) Omitting the message extension field for now. */ + } ResponseBatchItem; + + typedef struct request_message + { + RequestHeader *request_header; + /* TODO (ph) Change this to a linked list */ + RequestBatchItem *batch_items; + size_t batch_count; + } RequestMessage; + + typedef struct response_message + { + ResponseHeader *response_header; + /* TODO (ph) Change this to a linked list */ + ResponseBatchItem *batch_items; + size_t batch_count; + } ResponseMessage; + + typedef struct functions + { + LinkedList *function_list; + } Functions; + + typedef struct operations + { + LinkedList *operation_list; + } Operations; + + typedef struct object_types + { + LinkedList *object_list; + } ObjectTypes; + + typedef struct alternative_endpoints + { + LinkedList *endpoint_list; + } AltEndpoints; + + typedef struct server_information + { + TextString *server_name; + TextString *server_serial_number; + TextString *server_version; + TextString *server_load; + TextString *product_name; + TextString *build_level; + TextString *build_date; + TextString *cluster_info; + AltEndpoints *alternative_failover_endpoints; + // Vendor-Specific Any, MAY be repeated + } ServerInformation; + + /* + typedef struct application_namespaces + { + LinkedList *app_namespace_list; + } ApplicationNamespaces; + */ + + typedef struct query_request_payload + { + Functions *functions; + } QueryRequestPayload; + + typedef struct query_response_payload + { + Operations *operations; // Specifies an Operation that is supported by the server. + ObjectTypes *objects; // Specifies a Managed Object Type that is supported + // by the server. + TextString *vendor_identification; // SHALL be returned if Query Server + // Information is requested. The Vendor + // Identification SHALL be a text string + // that uniquely identifies the vendor. + ServerInformation *server_information; // Contains vendor-specific information possibly + // be of interest to the client. + // ApplicationNamespaces* application_namespaces; // Specifies an + // Application Namespace supported by the server. Extension Information No, + // MAY be repeated // SHALL be returned if Query Extension List or Query + // Extension Map is requested and supported by the server. Attestation Type + // No, MAY be repeated // Specifies an Attestation Type that is supported + // by the server. RNG Parameters No, MAY be repeated // + // Specifies the RNG that is supported by the server. Profile Information + // No, MAY be repeated // Specifies the Profiles that are supported by the + // server. Validation Information No, MAY be repeated // Specifies + // the validations that are supported by the server. Capability Information + // No, MAY be repeated // Specifies the capabilities that are supported by + // the server. Client Registration Method No, MAY be repeated // + // Specifies a Client Registration Method that is supported by the server. + // Defaults Information No // Specifies the + // defaults that the server will use if the client omits them. Protection + // Storage Masks Yes // Specifies the list of + // Protection Storage Mask values supported by the server. A server MAY + // elect to provide an empty list in the Response if it is unable or + // unwilling to provide this information. + } QueryResponsePayload; + +#define MAX_QUERY_LEN 128 +#define MAX_QUERY_OPS 0x40 +#define MAX_QUERY_OBJS 0x20 + + typedef struct query_response + { + size_t operations_size; + int operations[MAX_QUERY_OPS]; + size_t objects_size; + int objects[MAX_QUERY_OBJS]; + char vendor_identification[MAX_QUERY_LEN]; + bool32 server_information_valid; + char server_name[MAX_QUERY_LEN]; + char server_serial_number[MAX_QUERY_LEN]; + char server_version[MAX_QUERY_LEN]; + char server_load[MAX_QUERY_LEN]; + char product_name[MAX_QUERY_LEN]; + char build_level[MAX_QUERY_LEN]; + char build_date[MAX_QUERY_LEN]; + char cluster_info[MAX_QUERY_LEN]; + } QueryResponse; + + +#ifdef __cplusplus +} + +#endif +#endif // KMIP_KMIP_STRUCTS_H diff --git a/libkmip/include/libkmip_version.h b/libkmip/include/libkmip_version.h index 92f7d09..d502723 100644 --- a/libkmip/include/libkmip_version.h +++ b/libkmip/include/libkmip_version.h @@ -4,7 +4,7 @@ #define KMIP_LIB_VERSION_MAJOR 0 #define KMIP_LIB_VERSION_MINOR 3 -#define KMIP_LIB_VERSION_PATCH 1 +#define KMIP_LIB_VERSION_PATCH 4 #define KMIP_LIB_STRINGIFY_I(x) #x #define KMIP_LIB_TOSTRING_I(x) KMIP_LIB_STRINGIFY_I (x) diff --git a/libkmip/src/CMakeLists.txt b/libkmip/src/CMakeLists.txt index 2cc92cf..7ed441b 100644 --- a/libkmip/src/CMakeLists.txt +++ b/libkmip/src/CMakeLists.txt @@ -19,9 +19,15 @@ target_include_directories( $ $ ) + +set(KMIP_PUBLIC_HEADERS + "../include/kmip.h" + "../include/kmip_locate.h" + "../include/kmip_bio.h" +) + set_target_properties( - kmip PROPERTIES PUBLIC_HEADER - "../include/kmip.h" + kmip PROPERTIES PUBLIC_HEADER "${KMIP_PUBLIC_HEADERS}" ) diff --git a/libkmip/src/kmip.c b/libkmip/src/kmip.c index d9d775c..a26b5fb 100644 --- a/libkmip/src/kmip.c +++ b/libkmip/src/kmip.c @@ -869,6 +869,7 @@ kmip_check_enum_value (enum kmip_version version, enum tag t, int value) case KMIP_OP_CREATE: case KMIP_OP_GET: case KMIP_OP_GET_ATTRIBUTES: + case KMIP_OP_GET_ATTRIBUTE_LIST: case KMIP_OP_ACTIVATE: case KMIP_OP_DESTROY: case KMIP_OP_QUERY: @@ -1265,8 +1266,8 @@ kmip_init (KMIP *ctx, void *buffer, size_t buffer_size, enum kmip_version v) if (ctx->memcpy_func == NULL) ctx->memcpy_func = &kmip_memcpy; - ctx->max_message_size = 8192; - ctx->error_message_size = 200; + ctx->max_message_size = KMIP_MAX_MESSAGE_SIZE; + ctx->error_message_size = KMIP_ERROR_MESSAGE_SIZE; ctx->error_message = NULL; ctx->error_frame_count = 20; @@ -12304,7 +12305,9 @@ kmip_encode_request_batch_item (KMIP *ctx, const RequestBatchItem *value) case KMIP_OP_REVOKE: result = kmip_encode_revoke_request_payload (ctx, (RevokeRequestPayload *)value->request_payload); break; - + case KMIP_OP_GET_ATTRIBUTE_LIST: + result = kmip_encode_get_attribute_list_request_payload (ctx, (GetAttributeListRequestPayload *)value->request_payload); + break; default: kmip_push_error_frame (ctx, __func__, __LINE__); return (KMIP_NOT_IMPLEMENTED); @@ -12624,6 +12627,33 @@ kmip_encode_revoke_response_payload (KMIP *ctx, const RevokeResponsePayload *val return (KMIP_OK); } +int +kmip_encode_get_attribute_list_request_payload (KMIP *ctx, const GetAttributeListRequestPayload *value) +{ + int result = 0; + result = kmip_encode_int32_be (ctx, TAG_TYPE (KMIP_TAG_REQUEST_PAYLOAD, KMIP_TYPE_STRUCTURE)); + CHECK_RESULT (ctx, result); + + uint8 *length_index = ctx->index; + uint8 *value_index = ctx->index += 4; + + if (value->unique_identifier != NULL) + { + result = kmip_encode_text_string (ctx, KMIP_TAG_UNIQUE_IDENTIFIER, value->unique_identifier); + CHECK_RESULT (ctx, result); + } + + uint8 *curr_index = ctx->index; + ctx->index = length_index; + + result = kmip_encode_length (ctx, curr_index - value_index); + CHECK_RESULT (ctx, result); + + ctx->index = curr_index; + + return (KMIP_OK); +} + /* Decoding Functions */ @@ -15066,7 +15096,12 @@ kmip_decode_response_batch_item (KMIP *ctx, ResponseBatchItem *value) "RevokeResponsePayload structure"); result = kmip_decode_revoke_response_payload (ctx, value->response_payload); break; - + case KMIP_OP_GET_ATTRIBUTE_LIST: + value->response_payload = ctx->calloc_func (ctx->state, 1, sizeof (GetAttributeListResponsePayload)); + CHECK_NEW_MEMORY (ctx, value->response_payload, sizeof (GetAttributeListResponsePayload), + "GetAttributeListResponsePayload structure"); + result = kmip_decode_get_attribute_list_response_payload (ctx, value->response_payload); + break; default: kmip_push_error_frame (ctx, __func__, __LINE__); return (KMIP_NOT_IMPLEMENTED); @@ -15950,3 +15985,36 @@ kmip_decode_revoke_response_payload (KMIP *ctx, RevokeResponsePayload *value) return (KMIP_OK); } + +int kmip_decode_get_attribute_list_response_payload (KMIP *ctx, GetAttributeListResponsePayload *value) +{ + CHECK_BUFFER_FULL (ctx, 8); + + int result = 0; + int32 tag_type = 0; + uint32 length = 0; + + kmip_decode_int32_be (ctx, &tag_type); + CHECK_TAG_TYPE (ctx, tag_type, KMIP_TAG_RESPONSE_PAYLOAD, KMIP_TYPE_STRUCTURE); + + kmip_decode_length (ctx, &length); + CHECK_BUFFER_FULL (ctx, length); + + value->unique_identifier = ctx->calloc_func (ctx->state, 1, sizeof (TextString)); + CHECK_NEW_MEMORY (ctx, value->unique_identifier, sizeof (TextString), "UniqueIdentifier text string"); + + result = kmip_decode_text_string (ctx, KMIP_TAG_UNIQUE_IDENTIFIER, value->unique_identifier); + CHECK_RESULT (ctx, result); + + //decode all name tags + uint32 tag = kmip_peek_tag (ctx); + while (tag == KMIP_TAG_ATTRIBUTE_NAME) + { + // memory? + value->attribute_name = ctx->calloc_func (ctx->state, 1, sizeof (TextString)); + CHECK_NEW_MEMORY (ctx, value->attribute_name, sizeof (TextString), "AttributeName text string"); + result = kmip_decode_text_string (ctx, KMIP_TAG_ATTRIBUTE_NAME, value->attribute_name); + tag = kmip_peek_tag (ctx); + } + return (KMIP_OK); +} diff --git a/libkmip/src/kmip_bio.c b/libkmip/src/kmip_bio.c index cffe088..7a6664d 100644 --- a/libkmip/src/kmip_bio.c +++ b/libkmip/src/kmip_bio.c @@ -3093,7 +3093,8 @@ kmip_bio_get_secret (BIO *bio, char *id, int id_size, char **key, int *key_size) SecretData *secret = (SecretData *)pld->object; KeyBlock *block = secret->key_block; - if ((block->key_format_type != KMIP_KEYFORMAT_OPAQUE) || (block->key_wrapping_data != NULL)) + if ( ! (block->key_format_type == KMIP_KEYFORMAT_OPAQUE || block->key_format_type == KMIP_KEYFORMAT_RAW) + || (block->key_wrapping_data != NULL)) { kmip_free_response_message (&ctx, &resp_m); kmip_set_buffer (&ctx, NULL, 0);