From 56fecf1832c3ebc4626ddf5c598762833c362d5e Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Mon, 10 May 2021 17:13:36 +0200 Subject: [PATCH] libkmipclient: Add KMIP client shared library MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit libkmipclient is a shared library that provides an KMIP client to communicate with an KMIP server. KMIP stands for Key Management Interoperability Protocol, and is an extensible communication protocol that defines message formats for the manipulation of cryptographic keys on a key management server. Signed-off-by: Ingo Franzki Signed-off-by: Jan Höppner --- .gitignore | 5 + Makefile | 2 +- README.md | 23 +- common.mak | 4 + include/kmipclient/kmipclient.h | 2066 ++++++++++++++++ libkmipclient/Makefile | 130 + libkmipclient/attribute.c | 4011 +++++++++++++++++++++++++++++++ libkmipclient/https.c | 848 +++++++ libkmipclient/json.c | 649 +++++ libkmipclient/key.c | 1439 +++++++++++ libkmipclient/kmip.c | 1595 ++++++++++++ libkmipclient/kmip.h | 111 + libkmipclient/libkmipclient.map | 225 ++ libkmipclient/names.c | 2253 +++++++++++++++++ libkmipclient/names.h | 41 + libkmipclient/request.c | 1795 ++++++++++++++ libkmipclient/response.c | 1377 +++++++++++ libkmipclient/tls.c | 528 ++++ libkmipclient/ttlv.c | 511 ++++ libkmipclient/utils.c | 726 ++++++ libkmipclient/utils.h | 61 + libkmipclient/xml.c | 490 ++++ 22 files changed, 18886 insertions(+), 4 deletions(-) create mode 100644 include/kmipclient/kmipclient.h create mode 100644 libkmipclient/Makefile create mode 100644 libkmipclient/attribute.c create mode 100644 libkmipclient/https.c create mode 100644 libkmipclient/json.c create mode 100644 libkmipclient/key.c create mode 100644 libkmipclient/kmip.c create mode 100644 libkmipclient/kmip.h create mode 100644 libkmipclient/libkmipclient.map create mode 100644 libkmipclient/names.c create mode 100644 libkmipclient/names.h create mode 100644 libkmipclient/request.c create mode 100644 libkmipclient/response.c create mode 100644 libkmipclient/tls.c create mode 100644 libkmipclient/ttlv.c create mode 100644 libkmipclient/utils.c create mode 100644 libkmipclient/utils.h create mode 100644 libkmipclient/xml.c diff --git a/.gitignore b/.gitignore index e6784d7d..9d5ca4ca 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,11 @@ libekmfweb/detect-openssl-version.dep libekmfweb/libekmfweb.so libekmfweb/libekmfweb.so.1 libekmfweb/libekmfweb.so.1.0 +libkmipclient/check-dep-libkmipclient +libkmipclient/detect-openssl-version.dep +libkmipclient/libkmipclient.so +libkmipclient/libkmipclient.so.1 +libkmipclient/libkmipclient.so.1.0 libseckey/check-dep-libseckey libseckey/detect-openssl-version.dep libutil/*_example diff --git a/Makefile b/Makefile index 70c15909..cad67e79 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/ar include common.mak LIB_DIRS = libvtoc libutil libzds libdasd libvmdump libccw libvmcp libekmfweb \ - libseckey + libseckey libkmipclient TOOL_DIRS = zipl zdump fdasd dasdfmt dasdview tunedasd \ tape390 osasnmpd qetharp ip_watcher qethconf scripts zconf \ vmconvert vmcp man mon_tools dasdinfo vmur cpuplugd ipl_tools \ diff --git a/README.md b/README.md index 32fe4d5e..556e8f17 100644 --- a/README.md +++ b/README.md @@ -249,6 +249,12 @@ Package contents Management Foundation - Web Edition, and is used to manage keys in an enterprise. + * libkmipclient: + A shared library that provides an KMIP client to communicate with an KMIP + server. KMIP stands for Key Management Interoperability Protocol, and is an + extensible communication protocol that defines message formats for the + manipulation of cryptographic keys on a key management server. + * hsci: Manage HiperSockets Converged Interfaces (HSCI). @@ -285,11 +291,14 @@ build options: | pfm | `HAVE_PFM` | cpacfstats | | net-snmp | `HAVE_SNMP` | osasnmpd | | glibc-static | `HAVE_LIBC_STATIC` | zfcpdump | -| openssl | `HAVE_OPENSSL` | genprotimg, zkey, libekmfweb | +| openssl | `HAVE_OPENSSL` | genprotimg, zkey, libekmfweb, | +| | | libkmipclient | | cryptsetup | `HAVE_CRYPTSETUP2` | zkey-cryptsetup | -| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb | +| json-c | `HAVE_JSONC` | zkey-cryptsetup, libekmfweb, | +| | | libkmipclient | | glib2 | `HAVE_GLIB2` | genprotimg | -| libcurl | `HAVE_LIBCURL` | genprotimg, libekmfweb | +| libcurl | `HAVE_LIBCURL` | genprotimg, libekmfweb, libkmipclient | +| libxml2 | `HAVE_LIBXML2` | libkmipclient | | systemd | `HAVE_SYSTEMD` | hsavmcore | This table lists additional build or install options: @@ -444,3 +453,11 @@ the different tools are provided: add `HAVE_SYSTEMD=0` to the make invocation. Tip: you may skip the hsavmcore build by adding `HAVE_FUSE=0` to the make invocation. + +* libkmipclient: + For building the libkmipclient shared library you need openssl version 1.1.1 + or newer installed (openssl-devel.rpm). Also required are json-c version 0.13 + or newer (json-c-devel.rpm), libxml2 version 2.9.10 or newer + (libxml2-devel.rpm), and libcurl version 7.59 or newer (libcurl-devel.rpm). + Tip: you may skip the libkmipclient build by adding `HAVE_OPENSSL=0`, + `HAVE_JSONC=0`, `HAVE_LIBXML2=0`, or `HAVE_LIBCURL=0` to the make invocation. diff --git a/common.mak b/common.mak index d8847376..2afbca6d 100644 --- a/common.mak +++ b/common.mak @@ -378,6 +378,10 @@ $(rootdir)/libseckey/libseckey.a: $(rootdir)/libseckey $(MAKE) -C $(rootdir)/libseckey/ libseckey.a .PHONY: $(rootdir)/libseckey +$(rootdir)/libkmipclient/libkmipclient.so: $(rootdir)/libkmipclient + $(MAKE) -C $(rootdir)/libkmipclient/ libkmipclient.so +.PHONY: $(rootdir)/libkmipclient + $(rootdir)/zipl/boot/data.o: $(MAKE) -C $(rootdir)/zipl/boot/ data.o diff --git a/include/kmipclient/kmipclient.h b/include/kmipclient/kmipclient.h new file mode 100644 index 00000000..1a3d56cb --- /dev/null +++ b/include/kmipclient/kmipclient.h @@ -0,0 +1,2066 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ +#ifndef LIB_KMIPCLIENT_H +#define LIB_KMIPCLIENT_H + +#include +#include + +#include + +enum kmip_tag { + KMIP_TAG_ACTIVATION_DATE = 0x420001, + KMIP_TAG_APPLICATION_DATA = 0x420002, + KMIP_TAG_APPLICATION_NAMESPACE = 0x420003, + KMIP_TAG_APPLICATION_SPECIFIC_INFORMATION = 0x420004, + KMIP_TAG_ARCHIVE_DATE = 0x420005, /* deprecated since v1.1 */ + KMIP_TAG_ASYNCHRONOUS_CORRELATION_VALUE = 0x420006, + KMIP_TAG_ASYNCHRONOUS_INDICATOR = 0x420007, + KMIP_TAG_ATTRIBUTE = 0x420008, + KMIP_TAG_ATTRIBUTE_INDEX = 0x420009, /* v1.x only */ + 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_CANCELATION_RESULT = 0x420012, + KMIP_TAG_CERTIFICATE = 0x420013, + KMIP_TAG_CERTIFICATE_IDENTIFIER = 0x420014, /* deprecated since v1.1 */ + KMIP_TAG_CERTIFICATE_ISSUER = 0x420015, /* deprecated since v1.1 */ + KMIP_TAG_CERTIFICATE_ISSUER_ALTERNATIVE_NAME = 0x420016, /* deprecated since v1.1 */ + KMIP_TAG_CERTIFICATE_ISSUER_DISTINGUISHED_NAME = 0x420017, /* deprecated since v1.1 */ + KMIP_TAG_CERTIFICATE_REQUEST = 0x420018, + KMIP_TAG_CERTIFICATE_REQUEST_TYPE = 0x420019, + KMIP_TAG_CERTIFICATE_SUBJECT = 0x42001A, /* deprecated since v1.1 */ + KMIP_TAG_CERTIFICATE_SUBJECT_ALTERNATIVE_NAME = 0x42001B, /* deprecated since v1.1 */ + KMIP_TAG_CERTIFICATE_SUBJECT_DISTINGUISHED_NAME = 0x42001C, /* deprecated since v1.1 */ + KMIP_TAG_CERTIFICATE_TYPE = 0x42001D, + KMIP_TAG_CERTIFICATE_VALUE = 0x42001E, + KMIP_TAG_COMMON_TEMPLATE_ATTRIBUTE = 0x42001F, /* v1.x only */ + KMIP_TAG_COMPROMIZE_DATE = 0x420020, + KMIP_TAG_COMPROMISE_OCCURRENCE_DATE = 0x420021, + KMIP_TAG_CONTACT_INFORMATION = 0x420022, + KMIP_TAG_CREDENTIAL = 0x420023, + KMIP_TAG_CREDENTIAL_TYPE = 0x420024, + KMIP_TAG_CREDENTIAL_VALUE = 0x420025, + KMIP_TAG_CRITICALITY_INDICATOR = 0x420026, + KMIP_TAG_CRT_Coefficient = 0x420027, + KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM = 0x420028, + KMIP_TAG_CRYPTOGRAPHIC_DOMAIN_PARAMETERS = 0x420029, + KMIP_TAG_CRYPTOGRAPHIC_LENGTH = 0x42002A, + KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS = 0x42002B, + KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK = 0x42002C, + KMIP_TAG_CUSTOM_ATTRIBUTE = 0x42002D, /* v1.x only */ + KMIP_TAG_D = 0x42002E, + KMIP_TAG_DEACTIVATION_DATE = 0x42002F, + KMIP_TAG_DERIVATION_DATE = 0x420030, + KMIP_TAG_DERIVATION_DATA = 0x420031, + KMIP_TAG_DERIVATION_PARAMETERS = 0x420032, + KMIP_TAG_DESTROY_DATE = 0x420033, + KMIP_TAG_DIGEST = 0x420034, + KMIP_TAG_DIGEST_VALUE = 0x420035, + KMIP_TAG_ENCRYPTION_KEY_INFORMATION = 0x420036, + KMIP_TAG_G = 0x420037, + KMIP_TAG_HASHING_ALGORITHM = 0x420038, + KMIP_TAG_INITIAL_DATE = 0x420039, + KMIP_TAG_INITIALIZATION_VECTOR = 0x42003A, + KMIP_TAG_ISSUER = 0x42003B, /* deprecated since v1.1 */ + KMIP_TAG_ITERATION_COUNT = 0x42003C, + KMIP_TAG_IV_COUNTER_NONCE = 0x42003D, + KMIP_TAG_J = 0x42003E, + 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_PART_IDENTIFIER = 0x420044, + KMIP_TAG_KEY_VALUE = 0x420045, + KMIP_TAG_KEY_WRAPPING_DATA = 0x420046, + KMIP_TAG_KEY_WRAPPING_SPECIFICATION = 0x420047, + KMIP_TAG_LAST_CHANGE_DATE = 0x420048, + KMIP_TAG_LEASE_TIME = 0x420049, + KMIP_TAG_LINK = 0x42004A, + KMIP_TAG_LINK_TYPE = 0x42004B, + KMIP_TAG_LINKED_OBJECT_IDENTIFIER = 0x42004C, + 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_MESSAGE_EXTENSION = 0x420051, + KMIP_TAG_MODULUS = 0x420052, + 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_OFFSET = 0x420058, + KMIP_TAG_OPAQUE_DATA_TYPE = 0x420059, + KMIP_TAG_OPAQUE_DATA_VALUE = 0x42005A, + KMIP_TAG_OPAQUE_OBJECT = 0x42005B, + KMIP_TAG_OPERATION = 0x42005C, + KMIP_TAG_OPERATION_POLICY_NAME = 0x42005D, /* deprecated since v1.3 */ + KMIP_TAG_P = 0x42005E, + KMIP_TAG_PADDING_METHOD = 0x42005F, + KMIP_TAG_PRIME_EXPONENT_P = 0x420060, + KMIP_TAG_PRIME_EXPONENT_Q = 0x420061, + KMIP_TAG_PRIME_FIELD_SIZE = 0x420062, + KMIP_TAG_PRIVATE_EXPONENT = 0x420063, + KMIP_TAG_PRIVATE_KEY = 0x420064, + KMIP_TAG_PRIVATE_KEY_TEMPLATE_ATTRIBUTE = 0x420065, /* v1.x only */ + KMIP_TAG_PRIVATE_KEY_UNIQUE_IDENTIFIER = 0x420066, + 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_EXPONENT = 0x42006C, + KMIP_TAG_PUBLIC_KEY = 0x42006D, + KMIP_TAG_PUBLIC_KEY_TEMPLATE_ATTRIBUTE = 0x42006E, /* v1.x only */ + KMIP_TAG_PUBLIC_KEY_UNIQUE_IDENTIFIER = 0x42006F, + KMIP_TAG_PUT_FUNCTION = 0x420070, + KMIP_TAG_Q = 0x420071, + KMIP_TAG_Q_STRING = 0x420072, + KMIP_TAG_Q_LENGTH = 0x420073, + KMIP_TAG_QUERY_FUNCTION = 0x420074, + KMIP_TAG_RECOMMENDED_CURVE = 0x420075, + KMIP_TAG_REPLACED_UNIQUE_IDENTIFIER = 0x420076, + 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_REVOCATION_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_SERIAL_NUMBER = 0x420087, /* deprecated since v1.1 */ + KMIP_TAG_SERVER_INFORMATION = 0x420088, + KMIP_TAG_SPLIT_KEY = 0x420089, + KMIP_TAG_SPLIT_KEY_METHOD = 0x42008A, + KMIP_TAG_SPLIT_KEY_PARTS = 0x42008B, + KMIP_TAG_SPLIT_KEY_THRESHOLD = 0x42008C, + KMIP_TAG_STATE = 0x42008D, + KMIP_TAG_STORAGE_STATUS_MASK = 0x42008E, + KMIP_TAG_SYMMETRIC_KEY = 0x42008F, + KMIP_TAG_TEMPLATE = 0x420090, /* v1.x only */ + KMIP_TAG_TEMPLATE_ATTRIBUTE = 0x420091, /* v1.x only */ + KMIP_TAG_TIME_STAMP = 0x420092, + KMIP_TAG_UNIQUE_BATCH_ITEM_ID = 0x420093, + KMIP_TAG_UNIQUE_IDENTIFIER = 0x420094, + KMIP_TAG_USAGE_LIMITS = 0x420095, + KMIP_TAG_USAGE_LIMITS_COUNT = 0x420096, + KMIP_TAG_USAGE_LIMITS_TOTAL = 0x420097, + KMIP_TAG_USAGE_LIMITS_UNIT = 0x420098, + KMIP_TAG_USERNAME = 0x420099, + KMIP_TAG_VALIDITY_DATE = 0x42009A, + KMIP_TAG_VALIDITY_INDICATOR = 0x42009B, + KMIP_TAG_VENDOR_EXTENSION = 0x42009C, + KMIP_TAG_VENDOR_IDENTIFICATION = 0x42009D, + KMIP_TAG_WRAPPING_METHOD = 0x42009E, + KMIP_TAG_X = 0x42009F, + KMIP_TAG_Y = 0x4200A0, + KMIP_TAG_PASSWORD = 0x4200A1, + KMIP_TAG_DEVICE_IDENTIFIER = 0x4200A2, /* since v1.2 */ + KMIP_TAG_ENCODING_OPTION = 0x4200A3, /* since v1.2 */ + KMIP_TAG_EXTENSION_INFORMATION = 0x4200A4, /* since v1.2 */ + KMIP_TAG_EXTENSION_NAME = 0x4200A5, /* since v1.2 */ + KMIP_TAG_EXTENSION_TAG = 0x4200A6, /* since v1.2 */ + KMIP_TAG_EXTENSION_TYPE = 0x4200A7, /* since v1.2 */ + KMIP_TAG_FRESH = 0x4200A8, /* since v1.2 */ + KMIP_TAG_MACHINE_IDENTIFIER = 0x4200A9, /* since v1.2 */ + KMIP_TAG_MEDIA_IDENTIFIER = 0x4200AA, /* since v1.2 */ + KMIP_TAG_NETWORK_IDENTIFIER = 0x4200AB, /* since v1.2 */ + KMIP_TAG_OBJECT_GROUP_MEMBER = 0x4200AC, /* since v1.2 */ + KMIP_TAG_CERTIFICATE_LENGTH = 0x4200AD, /* since v1.2 */ + KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM = 0x4200AE, /* since v1.2 */ + KMIP_TAG_CERTIFICATE_SERIAL_NUMBER = 0x4200AF, /* since v1.2 */ + KMIP_TAG_DEVICE_SERIAL_NUMBER = 0x4200B0, /* since v1.2 */ + KMIP_TAG_ISSUER_ALTERNATE_NAME = 0x4200B1, /* since v1.2 */ + KMIP_TAG_ISSUER_DISTINGUISHED_NAME = 0x4200B2, /* since v1.2 */ + KMIP_TAG_SUBJECT_ALTERNATE_NAME = 0x4200B3, /* since v1.2 */ + KMIP_TAG_SUBJECT_DISTINGUISHED_NAME = 0x4200B4, /* since v1.2 */ + KMIP_TAG_X_509_CERTIFICATE_IDENTIFIER = 0x4200B5, /* since v1.2 */ + KMIP_TAG_X_509_CERTIFICATE_ISSUER = 0x4200B6, /* since v1.2 */ + KMIP_TAG_X_509_CERTIFICATE_SUBJECT = 0x4200B7, /* since v1.2 */ + KMIP_TAG_KEY_VALUE_LOCATION = 0x4200B8, /* since v1.2 */ + KMIP_TAG_KEY_VALUE_LOCATION_VALUE = 0x4200B9, /* since v1.2 */ + KMIP_TAG_KEY_VALUE_LOCATION_TYPE = 0x4200BA, /* since v1.2 */ + KMIP_TAG_KEY_VALUE_PRESENT = 0x4200BB, /* since v1.2 */ + KMIP_TAG_ORIGINAL_CREATION_DATE = 0x4200BC, /* since v1.2 */ + KMIP_TAG_PGP_KEY = 0x4200BD, /* since v1.2 */ + KMIP_TAG_PGP_KEY_VERSION = 0x4200BE, /* since v1.2 */ + KMIP_TAG_ALTERNATE_NAME = 0x4200BF, /* since v1.2 */ + KMIP_TAG_ALTERNATE_NAME_VALUE = 0x4200C0, /* since v1.2 */ + KMIP_TAG_ALTERNATE_NAME_TYPE = 0x4200C1, /* since v1.2 */ + KMIP_TAG_DATA = 0x4200C2, /* since v1.2 */ + KMIP_TAG_SIGNATURE_DATA = 0x4200C3, /* since v1.2 */ + KMIP_TAG_DATA_LENGTH = 0x4200C4, /* since v1.2 */ + KMIP_TAG_RANDOM_IV = 0x4200C5, /* since v1.2 */ + KMIP_TAG_MAC_DATA = 0x4200C6, /* since v1.2 */ + KMIP_TAG_ATTESTATION_TYPE = 0x4200C7, /* since v1.2 */ + KMIP_TAG_NONCE = 0x4200C8, /* since v1.2 */ + KMIP_TAG_NONCE_ID = 0x4200C9, /* since v1.2 */ + KMIP_TAG_NONCE_VALUE = 0x4200CA, /* since v1.2 */ + KMIP_TAG_ATTESTATION_MEASUREMENT = 0x4200CB, /* since v1.2 */ + KMIP_TAG_ATTESTATION_ASSERTION = 0x4200CC, /* since v1.2 */ + KMIP_TAG_IV_LENGTH = 0x4200CD, /* since v1.2 */ + KMIP_TAG_TAG_LENGTH = 0x4200CE, /* since v1.2 */ + KMIP_TAG_FIXED_FIELD_LENGTH = 0x4200CF, /* since v1.2 */ + KMIP_TAG_COUNTER_LENGTH = 0x4200D0, /* since v1.2 */ + KMIP_TAG_INITIAL_COUNTER_VALUE = 0x4200D1, /* since v1.2 */ + KMIP_TAG_INVOCATION_FIELD_LENGTH = 0x4200D2, /* since v1.2 */ + KMIP_TAG_ATTESTATION_CAPABLE_INDICATOR = 0x4200D3, /* since v1.2 */ + KMIP_TAG_OFFSET_ITEMS = 0x4200D4, /* since v1.3 */ + KMIP_TAG_LOCATED_ITEMS = 0x4200D5, /* since v1.3 */ + KMIP_TAG_CORRELATION_VALUE = 0x4200D6, /* since v1.3 */ + KMIP_TAG_INIT_INDICATOR = 0x4200D7, /* since v1.3 */ + KMIP_TAG_FINAL_INDICATOR = 0x4200D8, /* since v1.3 */ + KMIP_TAG_RNG_PARAMETERS = 0x4200D9, /* since v1.3 */ + KMIP_TAG_RNG_ALGORITHM = 0x4200DA, /* since v1.3 */ + KMIP_TAG_DRBG_ALGORITHM = 0x4200DB, /* since v1.3 */ + KMIP_TAG_FIPS186_VARIANT = 0x4200DC, /* since v1.3 */ + KMIP_TAG_PREDICTION_RESISTANCE = 0x4200DD, /* since v1.3 */ + KMIP_TAG_RANDOM_NUMBER_GENERATOR = 0x4200DE, /* since v1.3 */ + KMIP_TAG_VALIDATION_INFORMATION = 0x4200DF, /* since v1.3 */ + KMIP_TAG_VALIDATION_AUTHORITY_TYPE = 0x4200E0, /* since v1.3 */ + KMIP_TAG_VALIDATION_AUTHORITY_COUNTRY = 0x4200E1, /* since v1.3 */ + KMIP_TAG_VALIDATION_AUTHORITY_URI = 0x4200E2, /* since v1.3 */ + KMIP_TAG_VALIDATION_VERSION_MAJOR = 0x4200E3, /* since v1.3 */ + KMIP_TAG_VALIDATION_VERSION_MINOR = 0x4200E4, /* since v1.3 */ + KMIP_TAG_VALIDATION_TYPE = 0x4200E5, /* since v1.3 */ + KMIP_TAG_VALIDATION_LEVEL = 0x4200E6, /* since v1.3 */ + KMIP_TAG_VALIDATION_CERTIFICATE_IDENTIFIER = 0x4200E7, /* since v1.3 */ + KMIP_TAG_VALIDATION_CERTIFICATE_URI = 0x4200E8, /* since v1.3 */ + KMIP_TAG_VALIDATION_VENDOR_URI = 0x4200E9, /* since v1.3 */ + KMIP_TAG_VALIDATION_PROFILE = 0x4200EA, /* since v1.3 */ + KMIP_TAG_PROFILE_INFORMATION = 0x4200EB, /* since v1.3 */ + KMIP_TAG_PROFILE_NAME = 0x4200EC, /* since v1.3 */ + KMIP_TAG_SERVER_URI = 0x4200ED, /* since v1.3 */ + KMIP_TAG_SERVER_PORT = 0x4200EE, /* since v1.3 */ + KMIP_TAG_STREAMING_CAPABILITY = 0x4200EF, /* since v1.3 */ + KMIP_TAG_ASYNCHRONOUS_CAPABILITY = 0x4200F0, /* since v1.3 */ + KMIP_TAG_ATTESTATION_CAPABILITY = 0x4200F1, /* since v1.3 */ + KMIP_TAG_UNWRAP_MODE = 0x4200F2, /* since v1.3 */ + KMIP_TAG_DESTROY_ACTION = 0x4200F3, /* since v1.3 */ + KMIP_TAG_SHREDDING_ALGORITHM = 0x4200F4, /* since v1.3 */ + KMIP_TAG_RNG_MODE = 0x4200F5, /* since v1.3 */ + KMIP_TAG_CLIENT_REGISTRATION_METHOD = 0x4200F6, /* since v1.3 */ + KMIP_TAG_CAPABILITY_INFORMATION = 0x4200F7, /* since v1.3 */ + KMIP_TAG_KEY_WRAP_TYPE = 0x4200F8, /* since v1.4 */ + KMIP_TAG_BATCH_UNDO_CAPABILITY = 0x4200F9, /* since v1.4 */ + KMIP_TAG_BATCH_CONTINUE_CAPABILITY = 0x4200FA, /* since v1.4 */ + KMIP_TAG_PKCS_12_FRIENDLY_NAME = 0x4200FB, /* since v1.4 */ + KMIP_TAG_DESCRIPTION = 0x4200FC, /* since v1.4 */ + KMIP_TAG_COMMENT = 0x4200FD, /* since v1.4 */ + KMIP_TAG_AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA = 0x4200FE, /* since v1.4 */ + KMIP_TAG_AUTHENTICTAED_ENCRYPTION_TAG = 0x4200FF, /* since v1.4 */ + KMIP_TAG_SALT_LENGTH = 0x420100, /* since v1.4 */ + KMIP_TAG_MASK_GENERATOR = 0x420101, /* since v1.4 */ + KMIP_TAG_MASK_GENERATOR_HASHING_ALGORITHM = 0x420102, /* since v1.4 */ + KMIP_TAG_P_SOURCE = 0x420103, /* since v1.4 */ + KMIP_TAG_TRAILER_FIELD = 0x420104, /* since v1.4 */ + KMIP_TAG_CLIENT_CORRELATION_VALUE = 0x420105, /* since v1.4 */ + KMIP_TAG_SERVER_CORRELATION_VALUE = 0x420106, /* since v1.4 */ + KMIP_TAG_DIGESTED_DATA = 0x420107, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_CN = 0x420108, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_O = 0x420109, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_OU = 0x42010A, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_EMAIL = 0x42010B, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_C = 0x42010C, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_ST = 0x42010D, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_L = 0x42010E, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_UID = 0x42010F, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_SERIAL_NUMBER = 0x420110, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_TITLE = 0x420111, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_DC = 0x420112, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_SUBJECT_DN_QUALIFIER = 0x420113, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_CN = 0x420114, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_O = 0x420115, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_OU = 0x420116, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_EMAIL = 0x420117, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_C = 0x420118, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_ST = 0x420119, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_L = 0x42011A, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_UID = 0x42011B, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_SERIAL_NUMBER = 0x42011C, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_TITLE = 0x42011D, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_DC = 0x42011E, /* since v1.4 */ + KMIP_TAG_CERTIFICATE_ISSUER_DN_QUALIFIER = 0x42011F, /* since v1.4 */ + KMIP_TAG_SENSITIVE = 0x420120, /* since v1.4 */ + KMIP_TAG_ALWAYS_SENSITIVE = 0x420121, /* since v1.4 */ + KMIP_TAG_EXTRACTABLE = 0x420122, /* since v1.4 */ + KMIP_TAG_NEVER_EXTRACTABLE = 0x420123, /* since v1.4 */ + KMIP_TAG_REPLACE_EXISTING = 0x420124, /* since v1.4 */ + KMIP_TAG_ATTRIBUTES = 0x420125, /* since v2.0 */ + KMIP_TAG_COMMON_ATTRIBUTES = 0x420126, /* since v2.0 */ + KMIP_TAG_PRIVATE_KEY_ATTRIBUTES = 0x420127, /* since v2.0 */ + KMIP_TAG_PUBLIC_KEY_ATTRIBUTES = 0x420128, /* since v2.0 */ + KMIP_TAG_EXTENSION_ENUMERATION = 0x420129, /* since v2.0 */ + KMIP_TAG_EXTENSION_ATTRIBUTE = 0x42012A, /* since v2.0 */ + KMIP_TAG_EXTENSION_PARENT_STRUCTURE_TAG = 0x42012B, /* since v2.0 */ + KMIP_TAG_EXTENSION_DESCRIPTION = 0x42012C, /* since v2.0 */ + KMIP_TAG_SERVER_NAME = 0x42012D, /* since v2.0 */ + KMIP_TAG_SERVER_SERIAL_NUMBER = 0x42012E, /* since v2.0 */ + KMIP_TAG_SERVER_VERSION = 0x42012F, /* since v2.0 */ + KMIP_TAG_SERVER_LOAD = 0x420130, /* since v2.0 */ + KMIP_TAG_PRODUCT_NAME = 0x420131, /* since v2.0 */ + KMIP_TAG_BUILD_LEVEL = 0x420132, /* since v2.0 */ + KMIP_TAG_BUILD_DATE = 0x420133, /* since v2.0 */ + KMIP_TAG_CLUSTER_INFO = 0x420134, /* since v2.0 */ + KMIP_TAG_ALTERNATE_FAILOVER_ENDPOINTS = 0x420135, /* since v2.0 */ + KMIP_TAG_SHORT_UNIQUE_IDENTIFIER = 0x420136, /* since v2.0 */ + KMIP_TAG_TAG = 0x420138, /* since v2.0 */ + KMIP_TAG_CERTIFICATE_REQUEST_UNIQUE_IDENTIFIER = 0x420139, /* since v2.0 */ + KMIP_TAG_NIST_KEY_TYPE = 0x42013A, /* since v2.0 */ + KMIP_TAG_ATTRIBUTE_REFERENCE = 0x42013B, /* since v2.0 */ + KMIP_TAG_CURRENT_ATTRIBUTE = 0x42013C, /* since v2.0 */ + KMIP_TAG_NEW_ATTRIBUTE = 0x42013D, /* since v2.0 */ + KMIP_TAG_CERTIFICATE_REQUEST_VALUE = 0x420140, /* since v2.0 */ + KMIP_TAG_LOG_MESSAGE = 0x420141, /* since v2.0 */ + KMIP_TAG_PROFILE_VERSION = 0x420142, /* since v2.0 */ + KMIP_TAG_PROFILE_VERSION_MAJOR = 0x420143, /* since v2.0 */ + KMIP_TAG_PROFILE_VERSION_MINOR = 0x420144, /* since v2.0 */ + KMIP_TAG_PROTECTION_LEVEL = 0x420145, /* since v2.0 */ + KMIP_TAG_PROTECTION_PERIOD = 0x420146, /* since v2.0 */ + KMIP_TAG_QUANTUM_SAFE = 0x420147, /* since v2.0 */ + KMIP_TAG_QUANTUM_SAFE_CAPABILITY = 0x420148, /* since v2.0 */ + KMIP_TAG_TICKET = 0x420149, /* since v2.0 */ + KMIP_TAG_TICKET_TYPE = 0x42014A, /* since v2.0 */ + KMIP_TAG_TICKET_VALUE = 0x42014B, /* since v2.0 */ + KMIP_TAG_REQUEST_COUNT = 0x42014C, /* since v2.0 */ + KMIP_TAG_RIGHTS = 0x42014D, /* since v2.0 */ + KMIP_TAG_OBJECTS = 0x42014E, /* since v2.0 */ + KMIP_TAG_OPERATIONS = 0x42014F, /* since v2.0 */ + KMIP_TAG_RIGHT = 0x420150, /* since v2.0 */ + KMIP_TAG_ENDPOINT_ROLE = 0x420151, /* since v2.0 */ + KMIP_TAG_DEFAULTS_INFORMATION = 0x420152, /* since v2.0 */ + KMIP_TAG_OBJECT_DEFAULTS = 0x420153, /* since v2.0 */ + KMIP_TAG_EPHEMERAL = 0x420154, /* since v2.0 */ + KMIP_TAG_SERVER_HASHED_PASSWORD = 0x420155, /* since v2.0 */ + KMIP_TAG_ONE_TIME_PASSWORD = 0x420156, /* since v2.0 */ + KMIP_TAG_HASHED_PASSWORD = 0x420157, /* since v2.0 */ + KMIP_TAG_ADJUSTMENT_TYPE = 0x420158, /* since v2.0 */ + KMIP_TAG_PKCS_11_INTERFACE = 0x420159, /* since v2.0 */ + KMIP_TAG_PKCS_11_FUNCTION = 0x42015A, /* since v2.0 */ + KMIP_TAG_PKCS_11_INPUT_PARAMETERS = 0x42015B, /* since v2.0 */ + KMIP_TAG_PKCS_11_OUTPUT_PARAMETERS = 0x42015C, /* since v2.0 */ + KMIP_TAG_PKCS_11_RETURN_CODE = 0x42015D, /* since v2.0 */ + KMIP_TAG_PROTECTION_STORAGE_MASK = 0x42015E, /* since v2.0 */ + KMIP_TAG_PROTECTION_STORAGE_MASKS = 0x42015F, /* since v2.0 */ + KMIP_TAG_INTEROP_FUNCTION = 0x420160, /* since v2.0 */ + KMIP_TAG_INTEROP_IDENTIFIER = 0x420161, /* since v2.0 */ + KMIP_TAG_ADJUSTMENT_VALUE = 0x420162, /* since v2.0 */ + KMIP_TAG_COMMON_PROTECTION_STORAGE_MASKS = 0x420163, /* since v2.0 */ + KMIP_TAG_PRIVATE_PROTECTION_STORAGE_MASKS = 0x420164, /* since v2.0 */ + KMIP_TAG_PUBLIC_PROTECTION_STORAGE_MASKS = 0x420165, /* since v2.0 */ + KMIP_TAG_OBJECT_GROUPS = 0x420166, /* since v2.1 */ + KMIP_TAG_OBJECT_TYPES = 0x420167, /* since v2.1 */ + KMIP_TAG_CONSTRAINTS = 0x420168, /* since v2.1 */ + KMIP_TAG_CONSTRAINT = 0x420169, /* since v2.1 */ + KMIP_TAG_ROTATE_INTERVAL = 0x42016A, /* since v2.1 */ + KMIP_TAG_ROTATE_AUTOMATIC = 0x42016B, /* since v2.1 */ + KMIP_TAG_ROTATE_OFFSET = 0x42016C, /* since v2.1 */ + KMIP_TAG_ROTATE_DATE = 0x42016D, /* since v2.1 */ + KMIP_TAG_ROTATE_GENERATION = 0x42016E, /* since v2.1 */ + KMIP_TAG_ROTATE_NAME = 0x42016F, /* since v2.1 */ + KMIP_TAG_ROTATE_NAME_VALUE = 0x420170, /* since v2.1 */ + KMIP_TAG_ROTATE_NAME_TYPE = 0x420171, /* since v2.1 */ + KMIP_TAG_ROTATE_LATEST = 0x420172, /* since v2.1 */ + KMIP_TAG_ASYNCHRONOUS_REQUEST = 0x420173, /* since v2.1 */ + KMIP_TAG_SUBMISSION_DATE = 0x420174, /* since v2.1 */ + KMIP_TAG_PROCESSING_STAGE = 0x420175, /* since v2.1 */ + KMIP_TAG_ASYNCHRONOUS_CORRELATION_VALUES = 0x420176, /* since v2.1 */ +}; + +enum kmip_type { + 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_TYPE_DATE_TIME_EXTENDED = 0x0B, /* Since v2.0 */ +}; + +enum kmip_operation { + KMIP_OPERATION_CREATE = 0x01, + KMIP_OPERATION_CREATE_KEY_PAIR = 0x02, + KMIP_OPERATION_REGISTER = 0x03, + KMIP_OPERATION_RE_KEY = 0x04, + KMIP_OPERATION_DERIVE_KEY = 0x05, + KMIP_OPERATION_CERTIFY = 0x06, + KMIP_OPERATION_RE_CERTIFY = 0x07, + KMIP_OPERATION_LOCATE = 0x08, + KMIP_OPERATION_CHECK = 0x09, + KMIP_OPERATION_GET = 0x0A, + KMIP_OPERATION_GET_ATTRIBUTES = 0x0B, + KMIP_OPERATION_GET_ATTRIBUTE_LIST = 0x0C, + KMIP_OPERATION_ADD_ATTRIBUTE = 0x0D, + KMIP_OPERATION_MODIFY_ATTRIBUTE = 0x0E, + KMIP_OPERATION_DELETE_ATTRIBUTE = 0x0F, + KMIP_OPERATION_OBTAIN_LEASE = 0x10, + KMIP_OPERATION_GET_USAGE_ALLOCATION = 0x11, + KMIP_OPERATION_ACTIVATE = 0x12, + KMIP_OPERATION_REVOKE = 0x13, + KMIP_OPERATION_DESTROY = 0x14, + KMIP_OPERATION_ARCHIVE = 0x15, + KMIP_OPERATION_RECOVER = 0x16, + KMIP_OPERATION_VALIDATE = 0x17, + KMIP_OPERATION_QUERY = 0x18, + KMIP_OPERATION_CANCEL = 0x19, + KMIP_OPERATION_POLL = 0x1A, + KMIP_OPERATION_NOTIFY = 0x1B, + KMIP_OPERATION_PUT = 0x1C, + KMIP_OPERATION_RE_KEY_KEY_PAIR = 0x1D, /* since v1.2 */ + KMIP_OPERATION_DISCOVER_VERSIONS = 0x1E, /* since v1.2 */ + KMIP_OPERATION_ENCRYPT = 0x1F, /* since v1.2 */ + KMIP_OPERATION_DECRYPT = 0x20, /* since v1.2 */ + KMIP_OPERATION_SIGN = 0x21, /* since v1.2 */ + KMIP_OPERATION_SIGNATURE_VERIFY = 0x22, /* since v1.2 */ + KMIP_OPERATION_MAC = 0x23, /* since v1.2 */ + KMIP_OPERATION_MAC_VERIFY = 0x24, /* since v1.2 */ + KMIP_OPERATION_RNG_RETRIEVE = 0x25, /* since v1.2 */ + KMIP_OPERATION_RNG_SEED = 0x26, /* since v1.2 */ + KMIP_OPERATION_HASH = 0x27, /* since v1.2 */ + KMIP_OPERATION_CREATE_SPLIT_KEY = 0x28, /* since v1.2 */ + KMIP_OPERATION_JOIN_SPLIT_KEY = 0x29, /* since v1.2 */ + KMIP_OPERATION_IMPORT = 0x2A, /* since v1.4 */ + KMIP_OPERATION_EXPORT = 0x2B, /* since v1.4 */ + KMIP_OPERATION_LOG = 0x2C, /* since v2.0 */ + KMIP_OPERATION_LOGIN = 0x2D, /* since v2.0 */ + KMIP_OPERATION_LOGOUT = 0x2E, /* since v2.0 */ + KMIP_OPERATION_DELEGATE_LOGIN = 0x2F, /* since v2.0 */ + KMIP_OPERATION_ADJUST_ATTRIBUTE = 0x30, /* since v2.0 */ + KMIP_OPERATION_SET_ATTRIBUTE = 0x31, /* since v2.0 */ + KMIP_OPERATION_SET_ENDPOINT_ROLE = 0x32, /* since v2.0 */ + KMIP_OPERATION_PKS_11 = 0x33, /* since v2.0 */ + KMIP_OPERATION_INTEROP = 0x34, /* since v2.0 */ + KMIP_OPERATION_RE_PROVISION = 0x35, /* since v2.0 */ + KMIP_OPERATION_SET_DEFAULTS = 0x36, /* since v2.1 */ + KMIP_OPERATION_SET_CONSTRAINTS = 0x37, /* since v2.1 */ + KMIP_OPERATION_GET_CONSTRAINTS = 0x38, /* since v2.1 */ + KMIP_OPERATION_QUERY_ASYNCHRONOUS_REQUESTS = 0x39, /* since v2.1 */ + KMIP_OPERATION_PROCESS = 0x3A, /* since v2.1 */ + KMIP_OPERATION_PING = 0x3B, /* since v2.1 */ +}; + +enum kmip_batch_error_cont_option { + KMIP_BATCH_ERR_CONT_CONTINUE = 0x01, + KMIP_BATCH_ERR_CONT_STOP = 0x02, + KMIP_BATCH_ERR_CONT_UNDO = 0x03, +}; + +enum kmip_crypto_usage_mask { + KMIP_CRY_USAGE_MASK_SIGN = 0x00000001, + KMIP_CRY_USAGE_MASK_VERIFY = 0x00000002, + KMIP_CRY_USAGE_MASK_ENCRYPT = 0x00000004, + KMIP_CRY_USAGE_MASK_DECRYPT = 0x00000008, + KMIP_CRY_USAGE_MASK_WRAP_KEY = 0x00000010, + KMIP_CRY_USAGE_MASK_UNWRAP_KEY = 0x00000020, + KMIP_CRY_USAGE_MASK_EXPORT = 0x00000040, /* v1.x only */ + KMIP_CRY_USAGE_MASK_MAC_GENERATE = 0x00000080, + KMIP_CRY_USAGE_MASK_MAC_VERIFY = 0x00000100, + KMIP_CRY_USAGE_MASK_DERIVE_KEY = 0x00000200, + KMIP_CRY_USAGE_MASK_CONTENT_COMMITMENT = 0x00000400, /* v1.x only */ + KMIP_CRY_USAGE_MASK_KEY_AGREEMENT = 0x00000800, + KMIP_CRY_USAGE_MASK_CERTIFICATE_SIGN = 0x00001000, + KMIP_CRY_USAGE_MASK_CLR_SIGN = 0x00002000, + KMIP_CRY_USAGE_MASK_GENERATE_CRYPTOGRAM = 0x00004000, /* v1.x only */ + KMIP_CRY_USAGE_MASK_VALIDATE_CRYPTOGRAM = 0x00008000, /* v1.x only */ + KMIP_CRY_USAGE_MASK_TRANSLATE_ENCRYPT = 0x00010000, /* v1.x only */ + KMIP_CRY_USAGE_MASK_TRANSLATE_DECRYPT = 0x00020000, /* v1.x only */ + KMIP_CRY_USAGE_MASK_TRANSLATE_WRAP = 0x00040000, /* v1.x only */ + KMIP_CRY_USAGE_MASK_TRANSLATE_UNWRAP = 0x00080000, /* v1.x only */ + KMIP_CRY_USAGE_MASK_AUTHENTICATE = 0x00100000, /* since v2.0 */ + KMIP_CRY_USAGE_MASK_UNRESTRICTED = 0x00200000, /* since v2.0 */ + KMIP_CRY_USAGE_MASK_FPE_ENCRYPT = 0x00400000, /* since v2.0 */ + KMIP_CRY_USAGE_MASK_FPE_DECRYPT = 0x00800000, /* since v2.0 */ +}; + +enum kmip_result_status { + KMIP_RESULT_STATUS_SUCCESS = 0x00, + KMIP_RESULT_STATUS_OPERATION_FAILED = 0x01, + KMIP_RESULT_STATUS_OPERATION_PENDING = 0x02, + KMIP_RESULT_STATUS_OPERATION_UNDONE = 0x03, +}; + +enum kmip_result_reason { + KMIP_RESULT_REASON_ITEM_NOT_FOUND = 0x01, + KMIP_RESULT_REASON_RESPONSE_TOO_LARGE = 0x02, + KMIP_RESULT_REASON_AUTH_NOT_SUCCESSFUL = 0x03, + KMIP_RESULT_REASON_INVALID_MESSAGE = 0x04, + KMIP_RESULT_REASON_OPERATION_NOT_SUCCESSFUL = 0x05, + KMIP_RESULT_REASON_MISSING_DATA = 0x06, + KMIP_RESULT_REASON_INVALIUD_FIELD = 0x07, + KMIP_RESULT_REASON_FEATURE_NOT_SUPPORTED = 0x08, + KMIP_RESULT_REASON_OP_CANCELED_BY_REQUESTOR = 0x09, + KMIP_RESULT_REASON_CRYPTOGRAPHIC_FAILURE = 0x0A, + KMIP_RESULT_REASON_ILLEGAL_OPERATION = 0x0B, /* v 1.x only */ + KMIP_RESULT_REASON_PERMISSION_DENIED = 0x0C, + KMIP_RESULT_REASON_OBJECT_ARCHIVED = 0x0D, + KMIP_RESULT_REASON_INDEX_OUT_OF_BOUNDS = 0x0E, /* v 1.x only */ + KMIP_RESULT_REASON_APP_NAMESPACE_NOT_SUPPORTED = 0x0F, + KMIP_RESULT_REASON_KEY_FORMAT_TYPE_NOT_SUPPORTED = 0x10, + KMIP_RESULT_REASON_KEY_COMPRESSION_TYPE_NOT_SUPPORTED = 0x11, + KMIP_RESULT_REASON_ENCODING_OPTION_ERROR = 0x12, /* since v1.2 */ + KMIP_RESULT_REASON_KEY_VALUE_NOT_PRESENT = 0x13, /* since v1.2 */ + KMIP_RESULT_REASON_ATTESTATION_REQUIRED = 0x14, /* since v1.2 */ + KMIP_RESULT_REASON_ATTESTATION_FAILED = 0x15, /* since v1.2 */ + KMIP_RESULT_REASON_SENSITIVE = 0x16, /* since v1.4 */ + KMIP_RESULT_REASON_NOT_EXTRACTABLE = 0x17, /* since v1.4 */ + KMIP_RESULT_REASON_OBJECT_ALREADY_EXISTS = 0x18, /* since v1.4 */ + KMIP_RESULT_REASON_INVALID_TICKET = 0x19, /* since v2.0 */ + KMIP_RESULT_REASON_USAGE_LIMIT_EXCEEDED = 0x1A, /* since v2.0 */ + KMIP_RESULT_REASON_NUMERIC_RANGE = 0x1B, /* since v2.0 */ + KMIP_RESULT_REASON_INVALID_DATA_TYPE = 0x1C, /* since v2.0 */ + KMIP_RESULT_REASON_READ_ONLY_ATTRIBUTE = 0x1D, /* since v2.0 */ + KMIP_RESULT_REASON_MULTI_VALUED_ATTRIBUTE = 0x1E, /* since v2.0 */ + KMIP_RESULT_REASON_UNSUPPORTED_ATTRIBUTE = 0x1F, /* since v2.0 */ + KMIP_RESULT_REASON_ATTRIBUTE_INSTANCE_NOT_FOUND = 0x20, /* since v2.0 */ + KMIP_RESULT_REASON_ATTRIBUTE_NOT_FOUND = 0x21, /* since v2.0 */ + KMIP_RESULT_REASON_ATTRIBUTE_READ_ONLY = 0x22, /* since v2.0 */ + KMIP_RESULT_REASON_ATTRIBUTE_SINGLE_VALUED = 0x23, /* since v2.0 */ + KMIP_RESULT_REASON_BAD_CRYPTOGRAPHIC_PARAMETERS = 0x24, /* since v2.0 */ + KMIP_RESULT_REASON_BAD_PASSWORD = 0x25, /* since v2.0 */ + KMIP_RESULT_REASON_CODEC_ERROR = 0x26, /* since v2.0 */ + KMIP_RESULT_REASON_ILLEGAL_OBJECT_TYPE = 0x28, /* since v2.0 */ + KMIP_RESULT_REASON_INCOMPATIBLE_CRYPTO_USAGE_MASK = 0x29, /* since v2.0 */ + KMIP_RESULT_REASON_INTERNAL_SERVER_ERROR = 0x2A, /* since v2.0 */ + KMIP_RESULT_REASON_INVALID_ASYNC_CORRELATION_VALUE = 0x2B, /* since v2.0 */ + KMIP_RESULT_REASON_INVALID_ATTRIBUTE = 0x2C, /* since v2.0 */ + KMIP_RESULT_REASON_INVALID_ATTRIBUTE_VALUE = 0x2D, /* since v2.0 */ + KMIP_RESULT_REASON_INVALID_CORRELATION_VALUE = 0x2E, /* since v2.0 */ + KMIP_RESULT_REASON_INVALID_CSR = 0x2F, /* since v2.0 */ + KMIP_RESULT_REASON_INVALID_OBJECT_TYPE = 0x30, /* since v2.0 */ + KMIP_RESULT_REASON_KEY_WRAP_TYPE_NOT_SUPPORTED = 0x32, /* since v2.0 */ + KMIP_RESULT_REASON_MISSING_INITIALIZATION_VECTOR = 0x34, /* since v2.0 */ + KMIP_RESULT_REASON_NOT_UNIQUE_NAME_ATTRIBUTE = 0x35, /* since v2.0 */ + KMIP_RESULT_REASON_OBJECT_DESTROYED = 0x36, /* since v2.0 */ + KMIP_RESULT_REASON_OBJECT_NOT_FOUND = 0x37, /* since v2.0 */ + KMIP_RESULT_REASON_NOT_AUTHORISED = 0x39, /* since v2.0 */ + KMIP_RESULT_REASON_SERVER_LIMIT_EXCEEDED = 0x3A, /* since v2.0 */ + KMIP_RESULT_REASON_UNKNOWN_ENUMERATION = 0x3B, /* since v2.0 */ + KMIP_RESULT_REASON_UNKNOWN_MESSAGE_EXTENSION = 0x3C, /* since v2.0 */ + KMIP_RESULT_REASON_UNKNOWN_TAG = 0x3D, /* since v2.0 */ + KMIP_RESULT_REASON_UNSUPPORTED_CRYPTO_PARAMETERS = 0x3E, /* since v2.0 */ + KMIP_RESULT_REASON_UNSUPPORTED_PROTOCOL_VERSION = 0x3F, /* since v2.0 */ + KMIP_RESULT_REASON_WRAPPING_OBJECT_ARCHIVED = 0x40, /* since v2.0 */ + KMIP_RESULT_REASON_WRAPPING_OBJECT_DESTROYED = 0x41, /* since v2.0 */ + KMIP_RESULT_REASON_WRAPPING_OBJECT_NOT_FOUND = 0x42, /* since v2.0 */ + KMIP_RESULT_REASON_WRONG_KEY_LIFECYCLE_STATE = 0x43, /* since v2.0 */ + KMIP_RESULT_REASON_PROTECTION_STORAGE_UNAVAILABLE = 0x44, /* since v2.0 */ + KMIP_RESULT_REASON_PKCS_11_CODE_ERROR = 0x45, /* since v2.0 */ + KMIP_RESULT_REASON_PKCS_11_INVALID_FUNCTION = 0x46, /* since v2.0 */ + KMIP_RESULT_REASON_PKCS_11_INVALID_INTERFACE = 0x47, /* since v2.0 */ + KMIP_RESULT_REASON_PRIVATE_PROT_STORAGE_UNAVAILABLE = 0x48, /* since v2.0 */ + KMIP_RESULT_REASON_PUBLIC_PROT_STORAGE_UNAVAILABLE = 0x49, /* since v2.0 */ + KMIP_RESULT_REASON_UNKNOWN_OBJECT_GROUP = 0x4A, /* since v2.1 */ + KMIP_RESULT_REASON_CONSTRAINT_VIOLATION = 0x4B, /* since v2.1 */ + KMIP_RESULT_REASON_DUPLICATE_PROCESS_REQUEST = 0x4C, /* since v2.1 */ + KMIP_RESULT_REASON_GENERAL_FAILURE = 0x100, +}; + +enum kmip_query_function { + KMIP_QUERY_OPERATIONS = 0x01, + KMIP_QUERY_OBJECTS = 0x02, + KMIP_QUERY_SERVER_INFORMATION = 0x03, + KMIP_QUERY_APPLICATION_NAMESPACES = 0x04, /* since v1.2 */ + KMIP_QUERY_EXTENSION_LIST = 0x05, /* since v1.2 */ + KMIP_QUERY_EXTENSION_MAP = 0x06, /* since v1.2 */ + KMIP_QUERY_ATTESTATION_TYPES = 0x07, /* since v1.2 */ + KMIP_QUERY_QUERY_RNGS = 0x08, /* since v1.3 */ + KMIP_QUERY_VALIDATIONS = 0x09, /* since v1.3 */ + KMIP_QUERY_PROFILES = 0x0A, /* since v1.3 */ + KMIP_QUERY_CAPABILITIES = 0x0B, /* since v1.3 */ + KMIP_QUERY_CLIENT_REGISTRATION_METHODS = 0x0C, /* since v1.3 */ + KMIP_QUERY_DEFAULTS_INFORMATION = 0x0D, /* since v2.0 */ + KMIP_QUERY_STORAGE_PROTECTION_MASKS = 0x0E, /* since v2.0 */ +}; + +enum kmip_name_type { + KMIP_NAME_TYPE_UNINTERPRETED_TEXT_STRING = 0x01, + KMIP_NAME_TYPE_URI = 0x02, +}; + +enum kmip_alternative_name_type { + KMIP_ALT_NAME_TYPE_UNINTERPRETED_TEXT_STRING = 0x01, + KMIP_ALT_NAME_TYPE_URI = 0x02, + KMIP_ALT_NAME_TYPE_OBJECT_SERIAL_NUMBER = 0x03, + KMIP_ALT_NAME_TYPE_EMAIL_ADDRESS = 0x04, + KMIP_ALT_NAME_TYPE_DNS_NAME = 0x05, + KMIP_ALT_NAME_TYPE_X_500_DISTINGUISHED_NAME = 0x06, + KMIP_ALT_NAME_TYPE_IP_ADDRESS = 0x07, +}; + +enum kmip_unique_identifier { + KMIP_UNIQUE_ID_ID_PLACEHOLDER = 0x01, /* since v2.0 */ + KMIP_UNIQUE_ID_CERTIFY = 0x02, /* since v2.0 */ + KMIP_UNIQUE_ID_CREATE = 0x03, /* since v2.0 */ + KMIP_UNIQUE_ID_CREATE_KEY_PAIR = 0x04, /* since v2.0 */ + KMIP_UNIQUE_ID_CREATE_KEY_PAIR_PRIVATE = 0x05, /* since v2.0 */ + KMIP_UNIQUE_ID_CREATE_KEY_PAIR_PUBLIC = 0x06, /* since v2.0 */ + KMIP_UNIQUE_ID_CREATE_SPLIT_KEY = 0x07, /* since v2.0 */ + KMIP_UNIQUE_ID_DERIVE_KEY = 0x08, /* since v2.0 */ + KMIP_UNIQUE_ID_IMPORT = 0x09, /* since v2.0 */ + KMIP_UNIQUE_ID_JOIN_SPLIT_KEY = 0x0A, /* since v2.0 */ + KMIP_UNIQUE_ID_LOCATE = 0x0B, /* since v2.0 */ + KMIP_UNIQUE_ID_REGISTER = 0x0C, /* since v2.0 */ + KMIP_UNIQUE_ID_RE_KEY = 0x0D, /* since v2.0 */ + KMIP_UNIQUE_ID_RE_CERTIFY = 0x0E, /* since v2.0 */ + KMIP_UNIQUE_ID_RE_KEY_KEY_PAIR = 0x0F, /* since v2.0 */ + KMIP_UNIQUE_ID_RE_KEY_KEY_PAIR_PRIVATE = 0x10, /* since v2.0 */ + KMIP_UNIQUE_ID_RE_KEY_KEY_PAIR_PUBLIC = 0x11, /* since v2.0 */ +}; + +enum kmip_object_type { + KMIP_OBJECT_TYPE_CERTIFICATE = 0x01, + KMIP_OBJECT_TYPE_SYMMETRIC_KEY = 0x02, + KMIP_OBJECT_TYPE_PUBLIC_KEY = 0x03, + KMIP_OBJECT_TYPE_PRIVATE_KEY = 0x04, + KMIP_OBJECT_TYPE_SPLIT_KEY = 0x05, + KMIP_OBJECT_TYPE_TEMPLATE = 0x06, /* v1.x only */ + KMIP_OBJECT_TYPE_SECRET_DATA = 0x07, + KMIP_OBJECT_TYPE_OPAQUE_OBJECT = 0x08, + KMIP_OBJECT_TYPE_PGP_KEY = 0x09, /* since v1.2 */ + KMIP_OBJECT_TYPE_CERTIFICATE_REQUEST = 0x0A, /* since v2.0 */ +}; + +enum kmip_crypto_algo { + KMIP_CRYPTO_ALGO_DES = 0x01, + KMIP_CRYPTO_ALGO_3DES = 0x02, + KMIP_CRYPTO_ALGO_AES = 0x03, + KMIP_CRYPTO_ALGO_RSA = 0x04, + KMIP_CRYPTO_ALGO_DSA = 0x05, + KMIP_CRYPTO_ALGO_ECDSA = 0x06, + KMIP_CRYPTO_ALGO_HMAC_SHA1 = 0x07, + KMIP_CRYPTO_ALGO_HMAC_SHA224 = 0x08, + KMIP_CRYPTO_ALGO_HMAC_SHA256 = 0x09, + KMIP_CRYPTO_ALGO_HMAC_SHA384 = 0x0A, + KMIP_CRYPTO_ALGO_HMAC_SHA512 = 0x0B, + KMIP_CRYPTO_ALGO_HMAC_MD5 = 0x0C, + KMIP_CRYPTO_ALGO_DH = 0x0D, + KMIP_CRYPTO_ALGO_ECDH = 0x0E, + KMIP_CRYPTO_ALGO_ECMQV = 0x0F, + KMIP_CRYPTO_ALGO_BLOWFISH = 0x10, + KMIP_CRYPTO_ALGO_CAMELLIA = 0x11, + KMIP_CRYPTO_ALGO_CAST5 = 0x12, + KMIP_CRYPTO_ALGO_IDEA = 0x13, + KMIP_CRYPTO_ALGO_MARS = 0x14, + KMIP_CRYPTO_ALGO_RC2 = 0x15, + KMIP_CRYPTO_ALGO_RC4 = 0x16, + KMIP_CRYPTO_ALGO_RC5 = 0x17, + KMIP_CRYPTO_ALGO_SKIPJACK = 0x18, + KMIP_CRYPTO_ALGO_TWOFISH = 0x19, + KMIP_CRYPTO_ALGO_EC = 0x1A, /* since v1.2 */ + KMIP_CRYPTO_ALGO_ONE_TIME_PAD = 0x1B, /* since v1.3 */ + KMIP_CRYPTO_ALGO_CHACHA20 = 0x1C, /* since v1.4 */ + KMIP_CRYPTO_ALGO_POLY1305 = 0x1D, /* since v1.4 */ + KMIP_CRYPTO_ALGO_CHACHA20_POLY1305 = 0x1E, /* since v1.4 */ + KMIP_CRYPTO_ALGO_SHA3_224 = 0x1F, /* since v1.4 */ + KMIP_CRYPTO_ALGO_SHA3_256 = 0x20, /* since v1.4 */ + KMIP_CRYPTO_ALGO_SHA3_384 = 0x21, /* since v1.4 */ + KMIP_CRYPTO_ALGO_SHA3_512 = 0x22, /* since v1.4 */ + KMIP_CRYPTO_ALGO_HMAC_SHA3_224 = 0x23, /* since v1.4 */ + KMIP_CRYPTO_ALGO_HMAC_SHA3_256 = 0x24, /* since v1.4 */ + KMIP_CRYPTO_ALGO_HMAC_SHA3_384 = 0x25, /* since v1.4 */ + KMIP_CRYPTO_ALGO_HMAC_SHA3_512 = 0x26, /* since v1.4 */ + KMIP_CRYPTO_ALGO_SHAKE_128 = 0x27, /* since v1.4 */ + KMIP_CRYPTO_ALGO_SHAKE_256 = 0x28, /* since v1.4 */ + KMIP_CRYPTO_ALGO_ARIA = 0x29, /* since v2.0 */ + KMIP_CRYPTO_ALGO_SEED = 0x2A, /* since v2.0 */ + KMIP_CRYPTO_ALGO_SM2 = 0x2B, /* since v2.0 */ + KMIP_CRYPTO_ALGO_SM3 = 0x2C, /* since v2.0 */ + KMIP_CRYPTO_ALGO_SM4 = 0x2D, /* since v2.0 */ + KMIP_CRYPTO_ALGO_GOST_R34_10_2012 = 0x2E, /* since v2.0 */ + KMIP_CRYPTO_ALGO_GOST_R34_11_2012 = 0x2F, /* since v2.0 */ + KMIP_CRYPTO_ALGO_GOST_R34_13_2015 = 0x30, /* since v2.0 */ + KMIP_CRYPTO_ALGO_GOST_28147_89 = 0x31, /* since v2.0 */ + KMIP_CRYPTO_ALGO_XMSS = 0x32, /* since v2.0 */ + KMIP_CRYPTO_ALGO_SPHINCS_256 = 0x33, /* since v2.0 */ + KMIP_CRYPTO_ALGO_MCELIECE = 0x34, /* since v2.0 */ + KMIP_CRYPTO_ALGO_MCELIECE_6960119 = 0x35, /* since v2.0 */ + KMIP_CRYPTO_ALGO_MCELIECE_8192128 = 0x36, /* since v2.0 */ + KMIP_CRYPTO_ALGO_ED25519 = 0x37, /* since v2.0 */ + KMIP_CRYPTO_ALGO_ED448 = 0x38, /* since v2.0 */ +}; + +enum kmip_certificate_type { + KMIP_CERTIFICATE_TYPE_X_509 = 0x01, + KMIP_CERTIFICATE_TYPE_PGP = 0x02, +}; + +enum kmip_state { + 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 kmip_protection_storage_mask { + KMIP_PROT_STORAGE_MASK_SOFTWARE = 0x00000001, + KMIP_PROT_STORAGE_MASK_HARDWARE = 0x00000002, + KMIP_PROT_STORAGE_MASK_ON_PROCESSOR = 0x00000004, + KMIP_PROT_STORAGE_MASK_ON_SYSTEM = 0x00000008, + KMIP_PROT_STORAGE_MASK_OFF_SYSTEM = 0x00000010, + KMIP_PROT_STORAGE_MASK_HYPERVISOR = 0x00000020, + KMIP_PROT_STORAGE_MASK_OPERATING_SYSTEM = 0x00000040, + KMIP_PROT_STORAGE_MASK_CONTAINER = 0x00000080, + KMIP_PROT_STORAGE_MASK_ON_PREMISES = 0x00000100, + KMIP_PROT_STORAGE_MASK_OFF_PREMISES = 0x00000200, + KMIP_PROT_STORAGE_MASK_SELF_MANAGED = 0x00000400, + KMIP_PROT_STORAGE_MASK_OUTSOURCED = 0x00000800, + KMIP_PROT_STORAGE_MASK_VALIDATED = 0x00001000, + KMIP_PROT_STORAGE_MASK_SAME_JURISDICATION = 0x00002000, +}; + +enum kmip_revoke_reason { + KMIP_REVOK_RSN_UNSPECIFIED = 0x01, + KMIP_REVOK_RSN_KEY_COMPROMISE = 0x02, + KMIP_REVOK_RSN_CA_COMPROMISE = 0x03, + KMIP_REVOK_RSN_AFFILIATION_CHANGED = 0x04, + KMIP_REVOK_RSN_SUPERSEDED = 0x05, + KMIP_REVOK_RSN_CESSATION_OF_OPERATION = 0x06, + KMIP_REVOK_RSN_PRIVILEGE_WITHDRAWN = 0x07, +}; + +enum kmip_object_group_member { + KMIP_OBJ_GROUP_MEMBER_FRESH = 0x01, + KMIP_OBJ_GROUP_MEMBER_DEFAULT = 0x02, +}; + +enum kmip_storage_status_mask { + KMIP_STORAGE_STATUS_MASK_ONLINE = 0x01, + KMIP_STORAGE_STATUS_MASK_ARCHIVAL = 0x02, + KMIP_STORAGE_STATUS_MASK_DESTTROYED = 0x04, +}; + +enum kmip_key_format_type { + KMIP_KEY_FORMAT_TYPE_RAW = 0x01, + KMIP_KEY_FORMAT_TYPE_OPAQUE = 0x02, + KMIP_KEY_FORMAT_TYPE_PKCS_1 = 0x03, + KMIP_KEY_FORMAT_TYPE_PKCS_8 = 0x04, + KMIP_KEY_FORMAT_TYPE_X_509 = 0x05, + KMIP_KEY_FORMAT_TYPE_EC_PRIVATE_KEY = 0x06, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_SYMMETRIC_KEY = 0x07, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DSA_PRIVATE_KEY = 0x08, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DSA_PUBLIC_KEY = 0x09, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_RSA_PRIVATE_KEY = 0x0A, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_RSA_PUBLIC_KEY = 0x0B, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DH_PRIVATE_KEY = 0x0C, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DH_PUBLIC_KEY = 0x0D, + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDSA_PRIVATE_KEY = 0x0E, /* deprecated since v1.3 */ + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDSA_PUBLIC_KEY = 0x0F, /* deprecated since v1.3 */ + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDH_PRIVATE_KEY = 0x10, /* deprecated since v1.3 */ + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDH_PUBLIC_KEY = 0x11, /* deprecated since v1.3 */ + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECMQV_PRIVATE_KEY = 0x12, /* deprecated since v1.3 */ + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECMQV_PUBLIC_KEY = 0x13, /* deprecated since v1.3 */ + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_EC_PRIVATE_KEY = 0x14, /* since v1.3 */ + KMIP_KEY_FORMAT_TYPE_TRANSPARENT_EC_PUBLIC_KEY = 0x15, /* since v1.3 */ + KMIP_KEY_FORMAT_TYPE_PKCS_12 = 0x16, /* since v1.4 */ + KMIP_KEY_FORMAT_TYPE_PKCS_10 = 0x17, /* since v2.0 */ +}; + +enum kmip_key_compression_type { + KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_UNCOMPRESSED = 0x01, + KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_COMPRESSED_PRIME = 0x02, + KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_COMPRESSED_CHAR2 = 0x03, + KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_HYBID = 0x04, +}; + +enum kmip_wrapping_method { + KMIP_WRAPPING_METHOD_ENCRYPT = 0x01, + KMIP_WRAPPING_METHOD_MAC_SIGN = 0x02, + KMIP_WRAPPING_METHOD_ENCRYPT_THEN_MAC_SIGN = 0x03, + KMIP_WRAPPING_METHOD_MAC_SIGN_THEN_ENCRYPT = 0x04, + KMIP_WRAPPING_METHOD_TR_31 = 0x05, +}; + +enum kmip_key_wrap_type { + KMIP_KEY_WRAP_TYPE_NOT_WRAPPED = 0x01, + KMIP_KEY_WRAP_TYPE_AS_REGISTERED = 0x02, +}; + +enum kmip_block_cipher_mode { + KMIP_BLOCK_CIPHER_MODE_CBC = 0x01, + KMIP_BLOCK_CIPHER_MODE_ECB = 0x02, + KMIP_BLOCK_CIPHER_MODE_PCBC = 0x03, + KMIP_BLOCK_CIPHER_MODE_CFB = 0x04, + KMIP_BLOCK_CIPHER_MODE_OFB = 0x05, + KMIP_BLOCK_CIPHER_MODE_CTR = 0x06, + KMIP_BLOCK_CIPHER_MODE_CMAC = 0x07, + KMIP_BLOCK_CIPHER_MODE_CCM = 0x08, + KMIP_BLOCK_CIPHER_MODE_GCM = 0x09, + KMIP_BLOCK_CIPHER_MODE_CBC_MAC = 0x0A, + KMIP_BLOCK_CIPHER_MODE_XTS = 0x0B, + KMIP_BLOCK_CIPHER_MODE_AES_KEY_WRAP_PADDING = 0x0C, + KMIP_BLOCK_CIPHER_MODE_NIST_KEY_WRAP = 0x0D, + KMIP_BLOCK_CIPHER_MODE_X9_102_AESKW = 0x0E, + KMIP_BLOCK_CIPHER_MODE_X9_102_TDKW = 0x0F, + KMIP_BLOCK_CIPHER_MODE_X9_102_AKW1 = 0x10, + KMIP_BLOCK_CIPHER_MODE_X9_102_AKW2 = 0x11, + KMIP_BLOCK_CIPHER_MODE_AEAD = 0x12, /* since v1.4 */ +}; + +enum kmip_padding_method { + KMIP_PADDING_METHOD_NONE = 0x01, + KMIP_PADDING_METHOD_OAEP = 0x02, + KMIP_PADDING_METHOD_PKCS5 = 0x03, + KMIP_PADDING_METHOD_SSL3 = 0x04, + KMIP_PADDING_METHOD_ZEROS = 0x05, + KMIP_PADDING_METHOD_ANSI_X9_23 = 0x06, + KMIP_PADDING_METHOD_ISO_10126 = 0x07, + KMIP_PADDING_METHOD_PKCS_1_5 = 0x08, + KMIP_PADDING_METHOD_X9_31 = 0x09, + KMIP_PADDING_METHOD_PSS = 0x0A, +}; + +enum kmip_hashing_algo { + KMIP_HASHING_ALGO_MD2 = 0x01, + KMIP_HASHING_ALGO_MD4 = 0x02, + KMIP_HASHING_ALGO_MD5 = 0x03, + KMIP_HASHING_ALGO_SHA_1 = 0x04, + KMIP_HASHING_ALGO_SHA_224 = 0x05, + KMIP_HASHING_ALGO_SHA_256 = 0x06, + KMIP_HASHING_ALGO_SHA_384 = 0x07, + KMIP_HASHING_ALGO_SHA_512 = 0x08, + KMIP_HASHING_ALGO_RIPEMD_160 = 0x09, + KMIP_HASHING_ALGO_TIGER = 0x0A, + KMIP_HASHING_ALGO_WIRLPOOL = 0x0B, + KMIP_HASHING_ALGO_SHA_512_224 = 0x0C, /* since v1.2 */ + KMIP_HASHING_ALGO_SHA_512_256 = 0x0D, /* since v1.2 */ + KMIP_HASHING_ALGO_SHA_3_224 = 0x0E, /* since v1.4 */ + KMIP_HASHING_ALGO_SHA_3_256 = 0x0F, /* since v1.4 */ + KMIP_HASHING_ALGO_SHA_3_384 = 0x10, /* since v1.4 */ + KMIP_HASHING_ALGO_SHA_3_512 = 0x11, /* since v1.4 */ +}; + +enum kmip_key_role_type { + KMIP_KEY_ROLE_TYPE_BDK = 0x01, + KMIP_KEY_ROLE_TYPE_CVK = 0x02, + KMIP_KEY_ROLE_TYPE_DEK = 0x03, + KMIP_KEY_ROLE_TYPE_KMAC = 0x04, + KMIP_KEY_ROLE_TYPE_MKSMC = 0x05, + KMIP_KEY_ROLE_TYPE_MKSMI = 0x06, + KMIP_KEY_ROLE_TYPE_MKDAC = 0x07, + KMIP_KEY_ROLE_TYPE_MKDN = 0x08, + KMIP_KEY_ROLE_TYPE_MKCP = 0x09, + KMIP_KEY_ROLE_TYPE_MKOTH = 0x0A, + KMIP_KEY_ROLE_TYPE_KEK = 0x0B, + KMIP_KEY_ROLE_TYPE_MAC16609 = 0x0C, + KMIP_KEY_ROLE_TYPE_MAC97971 = 0x0D, + KMIP_KEY_ROLE_TYPE_MAC97972 = 0x0E, + KMIP_KEY_ROLE_TYPE_MAC97973 = 0x0F, + KMIP_KEY_ROLE_TYPE_MAC97974 = 0x10, + KMIP_KEY_ROLE_TYPE_MAC97975 = 0x11, + KMIP_KEY_ROLE_TYPE_ZPK = 0x12, + KMIP_KEY_ROLE_TYPE_PVKIBM = 0x13, + KMIP_KEY_ROLE_TYPE_PVKPVV = 0x14, + KMIP_KEY_ROLE_TYPE_PVKOTH = 0x15, + KMIP_KEY_ROLE_TYPE_DUKPT = 0x16, /* since v1.4 */ + KMIP_KEY_ROLE_TYPE_IV = 0x17, /* since v1.4 */ + KMIP_KEY_ROLE_TYPE_TRKBK = 0x18, /* since v1.4 */ +}; + +enum kmip_signature_algo { + KMIP_SIGNATURE_ALGO_MD2_WITH_RSA_ENCRYPTION = 0x01, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_MD5_WITH_RSA_ENCRYPTION = 0x02, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_SHA_1_WITH_RSA_ENCRYPTION = 0x03, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_SHA_224_WITH_RSA_ENCRYPTION = 0x04, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_SHA_256_WITH_RSA_ENCRYPTION = 0x05, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_SHA_384_WITH_RSA_ENCRYPTION = 0x06, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_SHA_512_WITH_RSA_ENCRYPTION = 0x07, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_RSASSA_PSS = 0x08, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_DSA_WITH_SHA_1 = 0x09, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_DSA_WITH_SHA_244 = 0x0A, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_DSA_WITH_SHA_256 = 0x0B, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_1 = 0x0C, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_224 = 0x0D, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_256 = 0x0E, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_384 = 0x0F, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_512 = 0x10, /* since v1.2 */ + KMIP_SIGNATURE_ALGO_SHA3_256_WITH_RSA_ENCRYPTION = 0x11, /* since v1.4 */ + KMIP_SIGNATURE_ALGO_SHA3_385_WITH_RSA_ENCRYPTION = 0x12, /* since v1.4 */ + KMIP_SIGNATURE_ALGO_SHA3_512_WITH_RSA_ENCRYPTION = 0x13, /* since v1.4 */ +}; + +enum kmip_mask_generator { + KMIP_MASK_GENERATOR_MGF1 = 0x01, /* since v1.4 */ +}; + +enum kmip_encoding_option { + KMIP_ENCODING_OPTION_NO = 0x01, /* since v1.2 */ + KMIP_ENCODING_OPTION_TTLV = 0x02, /* since v1.2 */ +}; + +enum kmip_recommended_curve { + KMIP_REC_CURVE_P_192 = 0x01, + KMIP_REC_CURVE_K_163 = 0x02, + KMIP_REC_CURVE_B_163 = 0x03, + KMIP_REC_CURVE_P_224 = 0x04, + KMIP_REC_CURVE_K_223 = 0x05, + KMIP_REC_CURVE_B_223 = 0x06, + KMIP_REC_CURVE_P_256 = 0x07, + KMIP_REC_CURVE_K_283 = 0x08, + KMIP_REC_CURVE_B_283 = 0x09, + KMIP_REC_CURVE_P_384 = 0x0A, + KMIP_REC_CURVE_K_409 = 0x0B, + KMIP_REC_CURVE_B_409 = 0x0C, + KMIP_REC_CURVE_P_521 = 0x0D, + KMIP_REC_CURVE_K_571 = 0x0E, + KMIP_REC_CURVE_B_571 = 0x0F, + KMIP_REC_CURVE_SECP112R1 = 0x10, /* since v1.2 */ + KMIP_REC_CURVE_SECP112R2 = 0x11, /* since v1.2 */ + KMIP_REC_CURVE_SECP128R1 = 0x12, /* since v1.2 */ + KMIP_REC_CURVE_SECP128R2 = 0x13, /* since v1.2 */ + KMIP_REC_CURVE_SECP160K1 = 0x14, /* since v1.2 */ + KMIP_REC_CURVE_SECP160R1 = 0x15, /* since v1.2 */ + KMIP_REC_CURVE_SECP160R2 = 0x16, /* since v1.2 */ + KMIP_REC_CURVE_SECP192K1 = 0x17, /* since v1.2 */ + KMIP_REC_CURVE_SECP224K1 = 0x18, /* since v1.2 */ + KMIP_REC_CURVE_SECP256K1 = 0x19, /* since v1.2 */ + KMIP_REC_CURVE_SECT113R1 = 0x1A, /* since v1.2 */ + KMIP_REC_CURVE_SECT113R2 = 0x1B, /* since v1.2 */ + KMIP_REC_CURVE_SECT131R1 = 0x1C, /* since v1.2 */ + KMIP_REC_CURVE_SECT131R2 = 0x1D, /* since v1.2 */ + KMIP_REC_CURVE_SECT163R1 = 0x1E, /* since v1.2 */ + KMIP_REC_CURVE_SECT193R1 = 0x1F, /* since v1.2 */ + KMIP_REC_CURVE_SECT193R2 = 0x20, /* since v1.2 */ + KMIP_REC_CURVE_SECT239K1 = 0x21, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9P192V2 = 0x22, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9P192V3 = 0x23, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9P239V1 = 0x24, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9P239V2 = 0x25, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9P239V3 = 0x26, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB163V1 = 0x27, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB163V2 = 0x28, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB163V3 = 0x29, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB176V1 = 0x2A, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB191V1 = 0x2B, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB191V2 = 0x2C, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB191V3 = 0x2D, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB208W1 = 0x2E, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB239V1 = 0x2F, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB239V2 = 0x30, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB239V3 = 0x31, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB272W1 = 0x32, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB304W1 = 0x33, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB359V1 = 0x34, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2PNB368W1 = 0x35, /* since v1.2 */ + KMIP_REC_CURVE_ANSIX9C2TNB431R1 = 0x36, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP160R1 = 0x37, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP160T1 = 0x38, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP192R1 = 0x39, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP192T1 = 0x3A, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP224R1 = 0x3B, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP224T1 = 0x3C, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP256R1 = 0x3D, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP256T1 = 0x3E, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP320R1 = 0x3F, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP320T1 = 0x40, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP384R1 = 0x41, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP384T1 = 0x42, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP512R1 = 0x43, /* since v1.2 */ + KMIP_REC_CURVE_BRAINPOOLP512T1 = 0x44, /* since v1.2 */ + KMIP_REC_CURVE_CURVE25519 = 0x45, /* since v2.0 */ + KMIP_REC_CURVE_CURVE448 = 0x46, /* since v2.0 */ +}; + +enum kmip_protection_level { + KMIP_PROTECTION_LEVEL_HIGH = 0x01, /* since v2.0 */ + KMIP_PROTECTION_LEVEL_LOW = 0x02, /* since v2.0 */ +}; + +enum kmip_key_value_location_type { + KMIP_KEY_VAL_LOC_TYPE_UNINTERPRETED_TEXT_STRING = 0x01, + KMIP_KEY_VAL_LOC_TYPE_URI = 0x02, +}; + +enum kmip_link_type { + KMIP_LINK_TYPE_CERTIFICATE = 0x0101, + KMIP_LINK_TYPE_PUBLIC_KEY = 0x0102, + KMIP_LINK_TYPE_PRIVATE_KEY = 0x0103, + KMIP_LINK_TYPE_DERIVATION_BASE_OBJECT = 0x0104, + KMIP_LINK_TYPE_DERIVED_KEY = 0x0105, + KMIP_LINK_TYPE_REPLACEMENT_OBJECT = 0x0106, + KMIP_LINK_TYPE_REPLACED_OBJECT = 0x0107, + KMIP_LINK_TYPE_PARENT = 0x0108, /* since v1.2 */ + KMIP_LINK_TYPE_CHILD = 0x0109, /* since v1.2 */ + KMIP_LINK_TYPE_PREVIOUS = 0x010A, /* since v1.2 */ + KMIP_LINK_TYPE_NEXT = 0x010B, /* since v1.2 */ + KMIP_LINK_TYPE_PKCS_12_CERTIFICATE = 0x010C, /* since v1.4 */ + KMIP_LINK_TYPE_PKCS_12_PASSWORD = 0x010D, /* since v1.4 */ + KMIP_LINK_TYPE_WRAPPING_KEY = 0x010E, /* since v2.0 */ +}; + +enum kmip_client_registration_method { + KMIP_CLIENT_REG_METH_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_CLIENT_REG_METH_SERVER_PRE_GENERATED = 0x02, /* since v1.3 */ + KMIP_CLIENT_REG_METH_SERVER_ON_DEMAND = 0x03, /* since v1.3 */ + KMIP_CLIENT_REG_METH_CLIENT_GENERATED = 0x04, /* since v1.3 */ + KMIP_CLIENT_REG_METH_CLIENT_REGISTERED = 0x05, /* since v1.3 */ +}; + +enum kmip_rng_algorithm { + KMIP_RNG_ALGO_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_RNG_ALGO_FIPS_186_2 = 0x02, /* since v1.3 */ + KMIP_RNG_ALGO_DRBG = 0x03, /* since v1.3 */ + KMIP_RNG_ALGO_NRBG = 0x04, /* since v1.3 */ + KMIP_RNG_ALGO_ANSI_X9_31 = 0x05, /* since v1.3 */ + KMIP_RNG_ALGO_ANSI_X9_62 = 0x06, /* since v1.3 */ +}; + +enum kmip_drbg_algorithm { + KMIP_DRBG_ALGO_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_DRBG_ALGO_DUAL_EC = 0x02, /* since v1.3 */ + KMIP_DRBG_ALGO_HASH = 0x03, /* since v1.3 */ + KMIP_DRBG_ALGO_HMAC = 0x04, /* since v1.3 */ + KMIP_DRBG_ALGO_CTR = 0x05, /* since v1.3 */ +}; + +enum kmip_fips186_variation { + KMIP_FIPS186_VARI_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_FIPS186_VARI_GP_X_ORIGINAL = 0x02, /* since v1.3 */ + KMIP_FIPS186_VARI_GP_X_CHANGE_NOTICE = 0x03, /* since v1.3 */ + KMIP_FIPS186_VARI_X_ORIGINAL = 0x04, /* since v1.3 */ + KMIP_FIPS186_VARI_X_CHANGE_NOTICE = 0x05, /* since v1.3 */ + KMIP_FIPS186_VARI_K_ORIGINAL = 0x06, /* since v1.3 */ + KMIP_FIPS186_VARI_K_CHANGE_NOTICE = 0x07, /* since v1.3 */ +}; + +enum kmip_validation_authority_type { + KMIP_VALIDATION_AUTH_TYPE_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_VALIDATION_AUTH_TYPE_NIST_CMVP = 0x02, /* since v1.3 */ + KMIP_VALIDATION_AUTH_TYPE_COMMON_CRITERIA = 0x03, /* since v1.3 */ +}; + +enum kmip_validation_type { + KMIP_VALIDATION_TYPE_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_VALIDATION_TYPE_HARDWARE = 0x02, /* since v1.3 */ + KMIP_VALIDATION_TYPE_SOFTWARE = 0x03, /* since v1.3 */ + KMIP_VALIDATION_TYPE_FIRMWARE = 0x04, /* since v1.3 */ + KMIP_VALIDATION_TYPE_HYBRID = 0x05, /* since v1.3 */ +}; + +enum kmip_unwrap_mode { + KMIP_UNWRAP_MODE_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_UNWRAP_MODE_PROCESSED = 0x02, /* since v1.3 */ + KMIP_UNWRAP_MODE_NOT_PROCESSED = 0x03, /* since v1.3 */ +}; + +enum kmip_destroy_action { + KMIP_DESTROY_ACTION_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_DESTROY_ACTION_KEY_MATERIAL_DELETED = 0x02, /* since v1.3 */ + KMIP_DESTROY_ACTION_KEY_MATERIAL_SHREDDED = 0x03, /* since v1.3 */ + KMIP_DESTROY_ACTION_META_DATA_DELETED = 0x04, /* since v1.3 */ + KMIP_DESTROY_ACTION_META_DATA_SHREDDED = 0x05, /* since v1.3 */ + KMIP_DESTROY_ACTION_DELETED = 0x06, /* since v1.3 */ + KMIP_DESTROY_ACTION_SHREDDED = 0x07, /* since v1.3 */ +}; + +enum kmip_shredding_algorithm { + KMIP_SHREDDING_ALGO_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_SHREDDING_ALGO_CRYPTOGRAPHIC = 0x02, /* since v1.3 */ + KMIP_SHREDDING_ALGO_UNSUPPORTED = 0x03, /* since v1.3 */ +}; + +enum kmip_rng_mode { + KMIP_RNG_MODE_UNSPECIFIED = 0x01, /* since v1.3 */ + KMIP_RNG_MODE_SHARED_INSTANTIATION = 0x02, /* since v1.3 */ + KMIP_RNG_MODE_NON_SHARED_INSTANCIATION = 0x03, /* since v1.3 */ +}; + +enum kmip_KMIP_PROFILE_s { + KMIP_PROFILE_BASELINE_SERVER_BASIC_KMIP_V1_2 = 0x0001, + KMIP_PROFILE_BASELINE_SERVER_TLS_V1_2_KMIP_V1_2 = 0x0002, + KMIP_PROFILE_BASELINE_CLIENT_BASIC_KMIP_V1_2 = 0x0003, + KMIP_PROFILE_BASELINE_CLIENT_TLS_V1_2_KMIP_V1_2 = 0x0004, + KMIP_PROFILE_COMPLETE_SERVER_BASIC_KMIP_V1_2 = 0x0005, + KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2_KMIP_V1_2 = 0x0006, + KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_0 = 0x0007, + KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_1 = 0x0008, + KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_2 = 0x0009, + KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_0 = 0x000A, + KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_1 = 0x000B, + KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_2 = 0x000C, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_0 = 0x000D, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_1 = 0x000E, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_2 = 0x000F, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_0 = 0x0010, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_1 = 0x0011, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_2 = 0x0012, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_0 = 0x0013, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_1 = 0x0014, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_2 = 0x0015, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_0 = 0x0016, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_1 = 0x0017, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_2 = 0x0018, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT_KMIP_V1_2 = 0x0019, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER_KMIP_V1_2 = 0x001A, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT_KMIP_V1_2 = 0x001B, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER_KMIP_V1_2 = 0x001C, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT_KMIP_V1_2 = 0x001D, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER_KMIP_V1_2 = 0x001E, + KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_0 = 0x001F, + KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_0 + = 0x0020, + KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_0 + = 0x0021, + KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_1 = 0x0022, + KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_1 + = 0x0023, + KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_1 + = 0x0024, + KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_2 = 0x0025, + KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_2 + = 0x0026, + KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_2 + = 0x0027, + KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_0 = 0x0028, + KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_1 = 0x0029, + KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_2 = 0x002A, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_0 = 0x002B, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_1 = 0x002C, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_2 = 0x002D, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_0 = 0x002E, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_1 = 0x002F, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_2 = 0x0030, + KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_0 = 0x0031, + KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_1 = 0x0032, + KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_2 = 0x0033, + KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_0 = 0x0034, + KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_1 = 0x0035, + KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_2 = 0x0036, + KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_0 = 0x0037, + KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_1 = 0x0038, + KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_2 = 0x0039, + KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_0 = 0x003A, + KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_1 = 0x003B, + KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_2 = 0x003C, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_0 + = 0x003D, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_1 + = 0x003E, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_2 + = 0x003F, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_0 + = 0x0040, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_1 + = 0x0041, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_2 + = 0x0042, + KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_0 = 0x0043, + KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_1 = 0x0044, + KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_2 = 0x0045, + KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_0 = 0x0046, + KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_1 = 0x0047, + KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_2 = 0x0048, + KMIP_PROFILE_JSON_CLIENT_KMIP_V1_0 = 0x0049, + KMIP_PROFILE_JSON_CLIENT_KMIP_V1_1 = 0x004A, + KMIP_PROFILE_JSON_CLIENT_KMIP_V1_2 = 0x004B, + KMIP_PROFILE_JSON_SERVER_KMIP_V1_0 = 0x004C, + KMIP_PROFILE_JSON_SERVER_KMIP_V1_1 = 0x004D, + KMIP_PROFILE_JSON_SERVER_KMIP_V1_2 = 0x004E, + KMIP_PROFILE_XML_CLIENT_KMIP_V1_0 = 0x004F, + KMIP_PROFILE_XML_CLIENT_KMIP_V1_1 = 0x0050, + KMIP_PROFILE_XML_CLIENT_KMIP_V1_2 = 0x0051, + KMIP_PROFILE_XML_SERVER_KMIP_V1_0 = 0x0052, + KMIP_PROFILE_XML_SERVER_KMIP_V1_1 = 0x0053, + KMIP_PROFILE_XML_SERVER_KMIP_V1_2 = 0x0054, + KMIP_PROFILE_BASELINE_SERVER_BASIC_KMIP_V1_3 = 0x0055, + KMIP_PROFILE_BASELINE_SERVER_TLS_V1_2_KMIP_V1_3 = 0x0056, + KMIP_PROFILE_BASELINE_CLIENT_BASIC_KMIP_V1_3 = 0x0057, + KMIP_PROFILE_BASELINE_CLIENT_TLS_V1_2_KMIP_V1_3 = 0x0058, + KMIP_PROFILE_COMPLETE_SERVER_BASIC_KMIP_V1_3 = 0x0059, + KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2_KMIP_V1_3 = 0x005A, + KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_3 = 0x005B, + KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_3 = 0x005C, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_3 = 0x005D, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_3 = 0x005E, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_3 = 0x005F, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_3 = 0x0060, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT_KMIP_V1_3 = 0x0061, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER_KMIP_V1_3 = 0x0062, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT_KMIP_V1_3 = 0x0063, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER_KMIP_V1_3 = 0x0064, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT_KMIP_V1_3 = 0x0065, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER_KMIP_V1_3 = 0x0066, + KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_3 = 0x0067, + KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_3 + = 0x0068, + KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_3 + = 0x0069, + KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_3 = 0x006A, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_3 = 0x006B, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_3 = 0x006C, + KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_3 = 0x006D, + KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_3 = 0x006E, + KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_3 = 0x006F, + KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_3 = 0x0070, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_3 + = 0x0071, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_3 + = 0x0072, + KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_3 = 0x0073, + KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_3 = 0x0074, + KMIP_PROFILE_JSON_CLIENT_KMIP_V1_3 = 0x0075, + KMIP_PROFILE_JSON_SERVER_KMIP_V1_3 = 0x0076, + KMIP_PROFILE_XML_CLIENT_KMIP_V1_3 = 0x0077, + KMIP_PROFILE_XML_SERVER_KMIP_V1_3 = 0x0078, + KMIP_PROFILE_BASELINE_SERVER_BASIC_KMIP_V1_4 = 0x0079, + KMIP_PROFILE_BASELINE_SERVER_TLS_V1_2_KMIP_V1_4 = 0x007A, + KMIP_PROFILE_BASELINE_CLIENT_BASIC_KMIP_V1_4 = 0x007B, + KMIP_PROFILE_BASELINE_CLIENT_TLS_V1_2_KMIP_V1_4 = 0x007C, + KMIP_PROFILE_COMPLETE_SERVER_BASIC_KMIP_V1_4 = 0x007D, + KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2_KMIP_V1_4 = 0x007E, + KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_4 = 0x007F, + KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_4 = 0x0080, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_4 = 0x0081, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_4 = 0x0082, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_4 = 0x0083, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_4 = 0x0084, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT_KMIP_V1_4 = 0x0085, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER_KMIP_V1_4 = 0x0086, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT_KMIP_V1_4 = 0x0087, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER_KMIP_V1_4 = 0x0088, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT_KMIP_V1_4 = 0x0089, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER_KMIP_V1_4 = 0x008A, + KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_4 = 0x008B, + KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_4 + = 0x008C, + KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_4 + = 0x008D, + KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_4 = 0x008E, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_4 = 0x008F, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_4 = 0x0090, + KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_4 = 0x0091, + KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_4 = 0x0092, + KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_4 = 0x0093, + KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_4 = 0x0094, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_4 + = 0x0095, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_4 + = 0x0096, + KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_4 = 0x0097, + KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_4 = 0x0098, + KMIP_PROFILE_JSON_CLIENT_KMIP_V1_4 = 0x0099, + KMIP_PROFILE_JSON_SERVER_KMIP_V1_4 = 0x009A, + KMIP_PROFILE_XML_CLIENT_KMIP_V1_4 = 0x009B, + KMIP_PROFILE_XML_SERVER_KMIP_V1_4 = 0x009C, + KMIP_PROFILE_COMPLETE_SERVER_BASIC = 0x0104, + KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2 = 0x0105, + KMIP_PROFILE_TAPE_LIBRARY_CLIENT = 0x0106, + KMIP_PROFILE_TAPE_LIBRARY_SERVER = 0x0107, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT = 0x0108, + KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER = 0x0109, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT = 0x010A, + KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER = 0x010B, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT = 0x010C, + KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER = 0x010D, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT = 0x010E, + KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER = 0x010F, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT = 0x0110, + KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER = 0x0111, + KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT = 0x0112, + KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT = 0x0113, + KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT = 0x0114, + KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER = 0x0115, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT = 0x0116, + KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER = 0x0117, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT + = 0x011C, + KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER + = 0x011D, + KMIP_PROFILE_HTTPS_CLIENT = 0x011E, + KMIP_PROFILE_HTTPS_SERVER = 0x011F, + KMIP_PROFILE_JSON_CLIENT = 0x0120, + KMIP_PROFILE_JSON_SERVER = 0x0121, + KMIP_PROFILE_XML_CLIENT = 0x0122, + KMIP_PROFILE_XML_SERVER = 0x0123, + KMIP_PROFILE_AES_XTS_CLIENT = 0x0124, + KMIP_PROFILE_AES_XTS_SERVER = 0x0125, + KMIP_PROFILE_QUANTUM_SAFE_CLIENT = 0x0126, + KMIP_PROFILE_QUANTUM_SAFE_SERVER = 0x0127, + KMIP_PROFILE_PKCS_11_CLIENT = 0x0128, + KMIP_PROFILE_PKCS_11_SERVER = 0x0129, + KMIP_PROFILE_BASELINE_CLIENT = 0x012A, + KMIP_PROFILE_BASELINE_SERVER = 0x012B, + KMIP_PROFILE_COMPLETE_SERVER = 0x012C, +}; + +struct kmip_version { + int32_t major; + int32_t minor; +}; + +enum kmip_encoding { + KMIP_ENCODING_TTLV = 1, + KMIP_ENCODING_JSON = 2, /* Only via HTTPS transport */ + KMIP_ENCODING_XML = 3, /* Only via HTTPS transport */ +}; + +enum kmip_transport { + KMIP_TRANSPORT_PLAIN_TLS = 1, + KMIP_TRANSPORT_HTTPS = 2, +}; + +#define KMIP_DEFAULT_PLAIN_TLS_PORT "5696" +#define KMIP_DEFAULT_PLAIN_TLS_PORT_NUM 5696 +#define KMIP_DEFAULT_HTTPS_PORT "5696" +#define KMIP_DEFAULT_HTTPS_PORT_NUM 5696 + +struct kmip_conn_config { + /** Encoding used for the KMIP messages */ + enum kmip_encoding encoding; + /** Transport method used to deliver KMIP messages */ + enum kmip_transport transport; + /** + * The KMIP server. + * For Plain-TLS transport, only the hostname and optional port number. + * For HTTPS transport, an URL in the form + * 'https://hostname[:port]/uri' + */ + const char *server; + /** The client key as an OpenSSL PKEY object. */ + EVP_PKEY *tls_client_key; + /** File name of the client certificate PEM file */ + const char *tls_client_cert; + /** + * Optional: File name of the CA bundle PEM file, or a name of a + * directory the multiple CA certificates. If this is NULL, then the + * default system path for CA certificates is used + */ + const char *tls_ca; + /** + * Optional: File name of a PEM file holding a CA certificate of the + * issuer + */ + const char *tls_issuer_cert; + /** + * Optional: File name of a PEM file containing the servers pinned + * public key. Public key pinning requires that verify_peer or + * verify_host (or both) is true. + */ + const char *tls_pinned_pubkey; + /** + * Optional: File name of a PEM file containing the server's + * certificate. This can be used to allow peer verification with + * self-signed server certificates + */ + const char *tls_server_cert; + /** If true, the peer certificate is verified */ + bool tls_verify_peer; + /** + * If true, that the server certificate is for the server it is known + * as (i.e. the hostname in the url) + */ + bool tls_verify_host; + /** + * Optional: A list of ciphers for TLSv1.2 and below. This is a colon + * separated list of cipher strings. The format of the string is + * described in + * https://www.openssl.org/docs/man1.1.1/man1/ciphers.html + */ + const char *tls_cipher_list; + /** + * Optional: A list of ciphers for TLSv1.3. This is a colon separated + * list of TLSv1.3 ciphersuite names in order of preference. Valid + * TLSv1.3 ciphersuite names are: + * - TLS_AES_128_GCM_SHA256 + * - TLS_AES_256_GCM_SHA384 + * - TLS_CHACHA20_POLY1305_SHA256 + * - TLS_AES_128_CCM_SHA256 + * - TLS_AES_128_CCM_8_SHA256 + */ + const char *tls13_cipher_list; +}; + +/* Opaque KMIP node and connection structures */ +struct kmip_connection; +struct kmip_node; + +/* Generic KMIP node constructors/destructors and getters */ +struct kmip_node *kmip_node_clone(const struct kmip_node *node); +void kmip_node_upref(struct kmip_node *node); +void kmip_node_free(struct kmip_node *node); +enum kmip_tag kmip_node_get_tag(const struct kmip_node *node); +enum kmip_type kmip_node_get_type(const struct kmip_node *node); +char *kmip_node_get_name(const struct kmip_node *node); +void kmip_node_dump(struct kmip_node *node, bool debug); + +struct kmip_node *kmip_node_new_structure(enum kmip_tag tag, const char *name, + unsigned int num_elements, + struct kmip_node **elements); +struct kmip_node *kmip_node_new_structure_va(enum kmip_tag tag, + const char *name, + unsigned int num_elements, ...); +unsigned int kmip_node_get_structure_element_count( + const struct kmip_node *node); +struct kmip_node *kmip_node_get_structure_element_by_index( + const struct kmip_node *node, + unsigned int index); +unsigned int kmip_node_get_structure_element_by_tag_count( + const struct kmip_node *node, + enum kmip_tag tag); +struct kmip_node *kmip_node_get_structure_element_by_tag( + const struct kmip_node *node, + enum kmip_tag tag, unsigned int index); +int kmip_node_add_structure_element(struct kmip_node *node, + struct kmip_node *element); +int kmip_node_add_structure_elements(struct kmip_node *node, + unsigned int num_elements, + struct kmip_node **elements); + +struct kmip_node *kmip_node_new_integer(enum kmip_tag tag, const char *name, + int32_t value); +int32_t kmip_node_get_integer(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_long(enum kmip_tag tag, const char *name, + int64_t value); +int64_t kmip_node_get_long(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_bigint(enum kmip_tag tag, const char *name, + const BIGNUM *value); +const BIGNUM *kmip_node_get_bigint(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_enumeration(enum kmip_tag tag, const char *name, + uint32_t enumeration); +uint32_t kmip_node_get_enumeration(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_boolean(enum kmip_tag tag, const char *name, + bool value); +bool kmip_node_get_boolean(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_text_string(enum kmip_tag tag, const char *name, + const char *value); +const char *kmip_node_get_text_string(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_byte_string(enum kmip_tag tag, const char *name, + const unsigned char *value, + uint32_t length); +const unsigned char *kmip_node_get_byte_string(const struct kmip_node *node, + uint32_t *length); + +struct kmip_node *kmip_node_new_date_time(enum kmip_tag tag, const char *name, + int64_t value); +int64_t kmip_node_get_date_time(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_interval(enum kmip_tag tag, const char *name, + uint32_t value); +uint32_t kmip_node_get_interval(const struct kmip_node *node); + +struct kmip_node *kmip_node_new_date_time_ext(enum kmip_tag tag, + const char *name, + int64_t value); +int64_t kmip_node_get_date_time_ext(const struct kmip_node *node); + +/* Generic functions */ +void kmip_set_default_protocol_version(const struct kmip_version *version); +const struct kmip_version *kmip_get_default_protocol_version(void); + +/* Request related functions */ +struct kmip_node *kmip_new_protocol_version(const struct kmip_version *version); +struct kmip_node *kmip_new_profile_version(const struct kmip_version *version); +struct kmip_node *kmip_new_request_header(const struct kmip_version *version, + int32_t max_response_size, + const char *client_corr_value, + const char *server_corr_value, + bool asynchronous, + struct kmip_node *authentication, + enum kmip_batch_error_cont_option batch_err_opt, + bool batch_order_option, + int32_t batch_count); +struct kmip_node *kmip_new_request_batch_item(enum kmip_operation operation, + unsigned char *batch_id, + uint32_t batch_id_length, + struct kmip_node *payload); +struct kmip_node *kmip_new_request(struct kmip_node *request_header, + int32_t batch_count, + struct kmip_node **batch_items); +struct kmip_node *kmip_new_request_va(struct kmip_node *request_header, + int32_t batch_count, ...); +struct kmip_node *kmip_new_query_request_payload(unsigned int query_count, + const enum kmip_query_function *functions); +struct kmip_node *kmip_new_query_request_payload_va(unsigned int query_count, + ...); +struct kmip_node *kmip_new_discover_versions_payload(int version_count, + const struct kmip_version *versions); +struct kmip_node *kmip_new_discover_versions_payload_va(int version_count, ...); +struct kmip_node *kmip_new_protection_storage_masks(unsigned int masks_count, + int32_t *masks); +struct kmip_node *kmip_new_protection_storage_masks_va(unsigned int masks_count, + ...); +struct kmip_node *kmip_new_create_request_payload( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, + struct kmip_node **attrs); +struct kmip_node *kmip_new_create_request_payload_va( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, ...); +struct kmip_node *kmip_new_get_attribute_list_request_payload( + struct kmip_node *unique_id); +struct kmip_node *kmip_new_get_attributes_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + unsigned int num_attrs, + struct kmip_node **attr_refs); +struct kmip_node *kmip_new_get_attributes_request_payload_va( + const struct kmip_version *version, + struct kmip_node *unique_id, + unsigned int num_attrs, ...); +struct kmip_node *kmip_new_add_attribute_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + struct kmip_node *v2_attr); +struct kmip_node *kmip_new_modify_attribute_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + struct kmip_node *v2_current, + struct kmip_node *v2_attr); +struct kmip_node *kmip_new_set_attribute_v2_request_payload( + struct kmip_node *unique_id, + struct kmip_node *v2_attr); +struct kmip_node *kmip_new_delete_attribute_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + struct kmip_node *v2_current, + struct kmip_node *attr_ref); +struct kmip_node *kmip_new_activate_request_payload( + struct kmip_node *unique_id); +struct kmip_node *kmip_new_destroy_request_payload(struct kmip_node *unique_id); +struct kmip_node *kmip_new_archive_request_payload(struct kmip_node *unique_id); +struct kmip_node *kmip_new_recover_request_payload(struct kmip_node *unique_id); +struct kmip_node *kmip_new_revoke_request_payload(struct kmip_node *unique_id, + enum kmip_revoke_reason rsn, + const char *message, + uint64_t compromise_date); +struct kmip_node *kmip_new_locate_request_payload( + const struct kmip_version *version, + int32_t max_items, int32_t offset_items, + enum kmip_storage_status_mask storage_status, + enum kmip_object_group_member obj_group, + unsigned int attrs_count, + struct kmip_node **attrs); +struct kmip_node *kmip_new_locate_request_payload_va( + const struct kmip_version *version, + int32_t max_items, int32_t offset_items, + enum kmip_storage_status_mask storage_status, + enum kmip_object_group_member obj_group, + unsigned int attrs_count, ...); +struct kmip_node *kmip_new_register_request_payload( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *object, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, + struct kmip_node **attrs); +struct kmip_node *kmip_new_register_request_payload_va( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *object, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, ...); +struct kmip_node *kmip_new_get_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + enum kmip_key_format_type format_type, + enum kmip_key_wrap_type wrap_type, + enum kmip_key_compression_type compr_type, + struct kmip_node *wrap_specification); + +/* Response related functions */ +int kmip_get_protocol_version(const struct kmip_node *node, + struct kmip_version *version); +int kmip_get_profile_version(const struct kmip_node *node, + struct kmip_version *version); +int kmip_get_response_header(const struct kmip_node *node, + struct kmip_version *version, + int64_t *time_stamp, + const char **client_corr_value, + const char **server_corr_value, + int32_t *batch_count); +int kmip_get_response_batch_item(const struct kmip_node *node, + enum kmip_operation *operation, + const unsigned char **batch_id, + uint32_t *batch_id_length, + enum kmip_result_status *status, + enum kmip_result_reason *reason, + const char **message, + const unsigned char **async_corr_value, + uint32_t *async_corr_value_len, + struct kmip_node **payload); +int kmip_get_response(const struct kmip_node *node, + struct kmip_node **response_header, + unsigned int batch_index, + struct kmip_node **batch_item); +int kmip_get_query_response_payload(const struct kmip_node *node, + enum kmip_query_function query_function, + unsigned int *num_results, + unsigned int result_index, + struct kmip_node **result); +int kmip_get_discover_versions_response_payload(const struct kmip_node *node, + unsigned int *num_versions, + unsigned int index, + struct kmip_version *version); +int kmip_get_create_response_payload(const struct kmip_node *node, + enum kmip_object_type *obj_type, + struct kmip_node **unique_id, + unsigned int *num_attrs, + unsigned int attr_index, + struct kmip_node **attribute); +int kmip_get_get_attribute_list_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + unsigned int *num_attr_refs, + unsigned int index, + struct kmip_node **attr_ref); +int kmip_get_get_attributes_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + unsigned int *num_attrs, + unsigned int index, + struct kmip_node **v2_attr); +int kmip_get_add_attribute_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **v2_attr); +int kmip_get_modify_attribute_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **v2_attr); +int kmip_get_set_attribute_v2_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id); +int kmip_get_delete_attribute_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **v2_attr); +int kmip_get_activate_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id); +int kmip_get_destroy_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id); +int kmip_get_archive_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id); +int kmip_get_recover_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id); +int kmip_get_revoke_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id); +int kmip_get_activate_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id); +int kmip_get_locate_response_payload(const struct kmip_node *node, + int32_t *located_items, + unsigned int *num_items, + unsigned int index, + struct kmip_node **unique_id); +int kmip_get_register_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + unsigned int *num_attrs, + unsigned int attr_index, + struct kmip_node **attribute); +int kmip_get_get_response_payload(const struct kmip_node *node, + enum kmip_object_type *obj_type, + struct kmip_node **unique_id, + struct kmip_node **object); + +/* Attribute related functions */ +struct kmip_node *kmip_new_attributes(const struct kmip_version *version, + enum kmip_tag v2_tag, + unsigned int attrs_count, + struct kmip_node **v2_attrs); +struct kmip_node *kmip_new_attributes_va(const struct kmip_version *version, + enum kmip_tag v2_tag, + unsigned int attrs_count, ...); +int kmip_get_attributes(const struct kmip_node *node, unsigned int *num_attrs, + unsigned int attr_index, struct kmip_node **attr); + +struct kmip_node *kmip_new_vendor_attribute(const char *vendor_id, + const char *name, + struct kmip_node *value); +int kmip_get_vendor_attribute(const struct kmip_node *node, + const char **vendor_id, const char **name, + struct kmip_node **value); + +struct kmip_node *kmip_new_attribute_reference(enum kmip_tag attr_tag, + const char *vendor_id, + const char *name); +int kmip_get_attribute_reference(const struct kmip_node *node, + enum kmip_tag *attr_tag, + const char **vendor_id, const char **name); + +struct kmip_node *kmip_new_current_new_attribute(bool new_attr, + struct kmip_node *attr); + +struct kmip_node *kmip_new_unique_identifier(const char *text_id, + enum kmip_unique_identifier enum_id, + int32_t int_id); +int kmip_get_unique_identifier(const struct kmip_node *node, + const char **text_id, + enum kmip_unique_identifier *enum_id, + int32_t *int_id); + +struct kmip_node *kmip_new_name(const char *value, enum kmip_name_type type); +int kmip_get_name(const struct kmip_node *node, + const char **value, enum kmip_name_type *type); + +struct kmip_node *kmip_new_alternative_name(const char *value, + enum kmip_alternative_name_type type); +int kmip_get_alternative_name(const struct kmip_node *node, + const char **value, + enum kmip_alternative_name_type *type); + +struct kmip_node *kmip_new_object_type(enum kmip_object_type obj_type); +int kmip_get_object_type(const struct kmip_node *node, + enum kmip_object_type *obj_type); + +struct kmip_node *kmip_new_cryptographic_algorithm(enum kmip_crypto_algo algo); +int kmip_get_cryptographic_algorithm(const struct kmip_node *node, + enum kmip_crypto_algo *algo); + +struct kmip_node *kmip_new_cryptographic_length(int32_t length); +int kmip_get_cryptographic_length(const struct kmip_node *node, + int32_t *length); + +struct kmip_node *kmip_new_certificate_type(enum kmip_certificate_type type); +int kmip_get_certificate_type(const struct kmip_node *node, + enum kmip_certificate_type *type); + +struct kmip_node *kmip_new_cryptographic_usage_mask(int32_t usage_mask); +int kmip_get_cryptographic_usage_mask(const struct kmip_node *node, + int32_t *usage_mask); + +struct kmip_node *kmip_new_state(enum kmip_state state); +int kmip_get_state(const struct kmip_node *node, enum kmip_state *state); + +struct kmip_node *kmip_new_initial_date(int64_t date); +int kmip_get_initial_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_activation_date(int64_t date); +int kmip_get_activation_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_deactivation_date(int64_t date); +int kmip_get_deactivation_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_destroy_date(int64_t date); +int kmip_get_destroy_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_compromise_date(int64_t date); +int kmip_get_compromise_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_compromise_occurrence_date(int64_t date); +int kmip_get_compromise_occurrence_date(const struct kmip_node *node, + int64_t *date); + +struct kmip_node *kmip_new_last_change_date(int64_t date); +int kmip_get_last_change_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_original_creation_date(int64_t date); +int kmip_get_original_creation_date(const struct kmip_node *node, + int64_t *date); + +struct kmip_node *kmip_new_archive_date(int64_t date); +int kmip_get_archive_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_process_start_date(int64_t date); +int kmip_get_process_start_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_protect_stop_date(int64_t date); +int kmip_get_protect_stop_date(const struct kmip_node *node, int64_t *date); + +struct kmip_node *kmip_new_cryptographic_parameters( + const struct kmip_version *version, + enum kmip_block_cipher_mode mode, + enum kmip_padding_method padding, + enum kmip_hashing_algo hash_algo, + enum kmip_key_role_type key_role, + enum kmip_signature_algo signature_algo, + enum kmip_crypto_algo crypto_algo, + bool *random_iv, + int32_t *iv_length, + int32_t *tag_length, + int32_t *fixed_field_length, + int32_t *invoc_field_length, + int32_t *counter_length, + int32_t *init_counter_value, + int32_t *salt_length, + enum kmip_mask_generator mgf, + enum kmip_hashing_algo mgf_hash_algo, + int32_t *trailer_field); +int kmip_get_cryptographic_parameter(const struct kmip_node *node, + enum kmip_block_cipher_mode *mode, + enum kmip_padding_method *padding, + enum kmip_hashing_algo *hash_algo, + enum kmip_key_role_type *key_role, + enum kmip_signature_algo *signature_algo, + enum kmip_crypto_algo *crypto_algo, + bool *random_iv, + int32_t *iv_length, + int32_t *tag_length, + int32_t *fixed_field_length, + int32_t *invoc_field_length, + int32_t *counter_length, + int32_t *init_counter_value, + int32_t *salt_length, + enum kmip_mask_generator *mgf, + enum kmip_hashing_algo *mgf_hash_algo, + int32_t *trailer_field); + +struct kmip_node *kmip_new_cryptographic_domain_parameters( + int32_t qlength, + enum kmip_recommended_curve curve); +int kmip_get_cryptographic_domain_parameters(const struct kmip_node *node, + int32_t *qlength, + enum kmip_recommended_curve *curve); + +struct kmip_node *kmip_new_digital_signature_algorithm( + enum kmip_signature_algo signature_algo); +int kmip_get_digital_signature_algorithm(const struct kmip_node *node, + enum kmip_signature_algo *signature_algo); + +struct kmip_node *kmip_new_object_group(const char *group); +int kmip_get_object_group(const struct kmip_node *node, const char **group); + +struct kmip_node *kmip_new_revocation_reason(enum kmip_revoke_reason reason, + const char *message); +int kmip_get_revocation_reason(const struct kmip_node *node, + enum kmip_revoke_reason *reason, + const char **message); + +struct kmip_node *kmip_new_contact_information(const char *contact); +int kmip_get_contact_information(const struct kmip_node *node, + const char **contact); + +struct kmip_node *kmip_new_description(const char *description); +int kmip_get_description(const struct kmip_node *node, + const char **description); + +struct kmip_node *kmip_new_comment(const char *comment); +int kmip_get_comment(const struct kmip_node *node, const char **comment); + +struct kmip_node *kmip_new_key_format_type(enum kmip_key_format_type type); +int kmip_get_key_format_type(const struct kmip_node *node, + enum kmip_key_format_type *type); + +struct kmip_node *kmip_new_protection_level(enum kmip_protection_level level); +int kmip_get_protection_level(const struct kmip_node *node, + enum kmip_protection_level *level); + +struct kmip_node *kmip_new_protection_period(uint32_t period); +int kmip_get_protection_period(const struct kmip_node *node, uint32_t *period); + +struct kmip_node *kmip_new_protection_storage_mask(int32_t protection_mask); +int kmip_get_protection_storage_mask(const struct kmip_node *node, + int32_t *protection_mask); + +struct kmip_node *kmip_new_fresh(bool fresh); +int kmip_get_fresh(const struct kmip_node *node, bool *fresh); + +struct kmip_node *kmip_new_key_value_present(bool present); +int kmip_get_key_value_present(const struct kmip_node *node, bool *present); + +struct kmip_node *kmip_new_short_unique_identifier( + const unsigned char *short_uid, + uint32_t short_uid_len); +int kmip_get_short_unique_identifier(const struct kmip_node *node, + const unsigned char **short_uid, + uint32_t *short_uid_len); + +struct kmip_node *kmip_new_application_specific_information( + const char *name_space, const char *data); +int kmip_get_application_specific_information(const struct kmip_node *node, + const char **name_space, + const char **data); + +struct kmip_node *kmip_new_key_value_location(const char *value, + enum kmip_key_value_location_type type); +int kmip_get_key_value_location(const struct kmip_node *node, + const char **value, enum kmip_key_value_location_type *type); + +struct kmip_node *kmip_new_digest(enum kmip_hashing_algo hash_algo, + const unsigned char *digest, + uint32_t digest_len); +int kmip_get_digest(const struct kmip_node *node, + enum kmip_hashing_algo *hash_algo, + const unsigned char **digest, uint32_t *digest_len); + +struct kmip_node *kmip_new_sensitive(bool sensitive); +int kmip_get_sensitive(const struct kmip_node *node, bool *sensitive); + +struct kmip_node *kmip_new_always_sensitive(bool sensitive); +int kmip_get_always_sensitive(const struct kmip_node *node, bool *sensitive); + +struct kmip_node *kmip_new_extractable(bool extractable); +int kmip_get_extractable(const struct kmip_node *node, bool *extractable); + +struct kmip_node *kmip_new_never_extractable(bool extractable); +int kmip_get_never_extractable(const struct kmip_node *node, bool *extractable); + +struct kmip_node *kmip_new_link(enum kmip_link_type type, + struct kmip_node *obj_id); +int kmip_get_link(const struct kmip_node *node, enum kmip_link_type *type, + struct kmip_node **obj_id); + +struct kmip_node *kmip_new_linked_object_identifier(const char *text_id, + enum kmip_unique_identifier enum_id, + int32_t int_id); +int kmip_get_linked_object_identifier(const struct kmip_node *node, + const char **text_id, + enum kmip_unique_identifier *enum_id, + int32_t *int_id); + +struct kmip_node *kmip_new_operation_policy_name(const char *policy); +int kmip_get_operation_policy_name(const struct kmip_node *node, + const char **policy); + +struct kmip_node *kmip_new_lease_time(uint32_t lease_time); +int kmip_get_lease_time(const struct kmip_node *node, uint32_t *lease_time); + +/* Key related functions */ +struct kmip_node *kmip_new_key_block(enum kmip_key_format_type format_type, + enum kmip_key_compression_type compr_type, + struct kmip_node *key_value, + enum kmip_crypto_algo algorithm, + int32_t length, + struct kmip_node *wrappig_data); +int kmip_get_key_block(const struct kmip_node *node, + enum kmip_key_format_type *format_type, + enum kmip_key_compression_type *compr_type, + struct kmip_node **key_value, + enum kmip_crypto_algo *algorithm, + int32_t *length, + struct kmip_node **wrappig_data); + +struct kmip_node *kmip_new_key_value(const struct kmip_version *version, + struct kmip_node *key_material, + unsigned int attrs_count, + struct kmip_node **v2_attrs); +struct kmip_node *kmip_new_key_value_va(const struct kmip_version *version, + struct kmip_node *key_material, + unsigned int attrs_count, ...); +int kmip_get_key_value(const struct kmip_node *node, + struct kmip_node **key_material, + unsigned int *num_attrs, unsigned int index, + struct kmip_node **v2_attr); + +struct kmip_node *kmip_new_key_wrapping_data( + const struct kmip_version *version, + enum kmip_wrapping_method wrap_method, + struct kmip_node *encr_key_info, + struct kmip_node *mac_sign_key_info, + const unsigned char *mac_signature, + uint32_t mac_signature_len, + const unsigned char *iv_counter_nonce, + uint32_t iv_counter_nonce_len, + enum kmip_encoding_option encoding); +int kmip_get_key_wrapping_data(const struct kmip_node *node, + enum kmip_wrapping_method *wrap_method, + struct kmip_node **encr_key_info, + struct kmip_node **mac_sign_key_info, + const unsigned char **mac_signature, + uint32_t *mac_signature_len, + const unsigned char **iv_counter_nonce, + uint32_t *iv_counter_nonce_len, + enum kmip_encoding_option *encoding); + +struct kmip_node *kmip_new_key_wrapping_specification( + const struct kmip_version *version, + enum kmip_wrapping_method wrap_method, + struct kmip_node *encr_key_info, + struct kmip_node *mac_sign_key_info, + enum kmip_encoding_option encoding, + unsigned int attr_name_count, + const char **attr_names); +struct kmip_node *kmip_new_key_wrapping_specification_va( + const struct kmip_version *version, + enum kmip_wrapping_method wrap_method, + struct kmip_node *encr_key_info, + struct kmip_node *mac_sign_key_info, + enum kmip_encoding_option encoding, + unsigned int attr_name_count, ...); +int kmip_get_key_wrapping_specification(const struct kmip_node *node, + enum kmip_wrapping_method *wrap_method, + struct kmip_node **encr_key_info, + struct kmip_node **mac_sign_key_info, + enum kmip_encoding_option *encoding, + unsigned int *num_attr_names, + unsigned int attr_name_index, + const char **attr_name); + +struct kmip_node *kmip_new_key_info(bool mac_sign, struct kmip_node *unique_id, + struct kmip_node *crypto_params); +int kmip_get_key_info(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **crypto_params); + +struct kmip_node *kmip_new_transparent_symmetric_key(const unsigned char *key, + uint32_t key_length); +int kmip_get_transparent_symmetric_key(const struct kmip_node *node, + const unsigned char **key, + uint32_t *key_length); + +struct kmip_node *kmip_new_transparent_rsa_public_key(const BIGNUM *modulus, + const BIGNUM *pub_exp); +int kmip_get_transparent_rsa_public_key(const struct kmip_node *node, + const BIGNUM **modulus, + const BIGNUM **pub_exp); + +struct kmip_node *kmip_new_pkcs1_public_key(EVP_PKEY *pub_key); +int kmip_get_pkcs1_public_key(const struct kmip_node *node, + enum kmip_crypto_algo algo, + EVP_PKEY **pub_key); + +struct kmip_node *kmip_new_pkcs8_public_key(EVP_PKEY *pub_key); +int kmip_get_pkcs8_public_key(const struct kmip_node *node, + EVP_PKEY **pub_key); + +struct kmip_node *kmip_new_raw_key(const unsigned char *key, uint32_t key_len); +int kmip_get_raw_key(const struct kmip_node *node, const unsigned char **key, + uint32_t *key_len); + +struct kmip_node *kmip_new_symmetric_key(struct kmip_node *keyblock); +int kmip_get_symmetric_key(const struct kmip_node *node, + struct kmip_node **keyblock); + +struct kmip_node *kmip_new_public_key(struct kmip_node *keyblock); +int kmip_get_public_key(const struct kmip_node *node, + struct kmip_node **keyblock); + +/* Connection related functions */ +int kmip_connection_new(const struct kmip_conn_config *config, + struct kmip_connection **connection, + bool debug); +int kmip_connection_perform(struct kmip_connection *connection, + struct kmip_node *request, + struct kmip_node **response, + bool debug); +void kmip_connection_free(struct kmip_connection *connection); +int kmip_connection_get_server_cert(const char *server, + enum kmip_transport transport, + const char *ca, + EVP_PKEY *client_key, + const char *client_cert, + const char *server_cert_pem, + const char *server_pubkey_pem, + const char *cert_chain_pem, + bool *verified, + bool debug); + +#endif diff --git a/libkmipclient/Makefile b/libkmipclient/Makefile new file mode 100644 index 00000000..36efecb4 --- /dev/null +++ b/libkmipclient/Makefile @@ -0,0 +1,130 @@ +include ../common.mak + +VERSION = 1.0 +VERM = $(shell echo $(VERSION) | cut -d '.' -f 1) + +ifneq (${HAVE_OPENSSL},0) + ifneq (${HAVE_JSONC},0) + ifneq (${HAVE_LIBXML2},0) + ifneq (${HAVE_LIBCURL},0) + BUILD_TARGETS += libkmipclient.so.$(VERSION) + INSTALL_TARGETS += install-libkmipclient.so.$(VERSION) + else + BUILD_TARGETS += skip-libkmipclient-curl + INSTALL_TARGETS += skip-libkmipclient-curl + endif + else + BUILD_TARGETS += skip-libkmipclient-xml + INSTALL_TARGETS += skip-libkmipclient-xml + endif + else + BUILD_TARGETS += skip-libkmipclient-jsonc + INSTALL_TARGETS += skip-libkmipclient-jsonc + endif +else + BUILD_TARGETS += skip-libkmipclient-openssl + INSTALL_TARGETS += skip-libkmipclient-openssl +endif + +TMPFILE := $(shell mktemp) + +detect-openssl-version.dep: + echo "#include " > $(TMPFILE) + echo "#include " >> $(TMPFILE) + echo "#ifndef OPENSSL_VERSION_PREREQ" >> $(TMPFILE) + echo " #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR)" >> $(TMPFILE) + echo " #define OPENSSL_VERSION_PREREQ(maj, min) \\" >> $(TMPFILE) + echo " ((OPENSSL_VERSION_MAJOR << 16) + \\" >> $(TMPFILE) + echo " OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min))" >> $(TMPFILE) + echo " #else" >> $(TMPFILE) + echo " #define OPENSSL_VERSION_PREREQ(maj, min) \\" >> $(TMPFILE) + echo " (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | \\" >> $(TMPFILE) + echo " ((min) << 20)))" >> $(TMPFILE) + echo " #endif" >> $(TMPFILE) + echo "#endif" >> $(TMPFILE) + echo "#if !OPENSSL_VERSION_PREREQ(1, 1)" >> $(TMPFILE) + echo " #error openssl version 1.1 is required" >> $(TMPFILE) + echo "#endif" >> $(TMPFILE) + echo "static void __attribute__((unused)) test(void) {" >> $(TMPFILE) + echo " EVP_PKEY_meth_remove(NULL);" >> $(TMPFILE) + echo "}" >> $(TMPFILE) + mv $(TMPFILE) $@ + +check-dep-libkmipclient: detect-openssl-version.dep + $(call check_dep, \ + "libkmipclient", \ + "detect-openssl-version.dep", \ + "openssl-devel version >= 1.1.1", \ + "HAVE_OPENSSL=0", \ + -I. -lcrypto -DOPENSSL_SUPPRESS_DEPRECATED) + $(call check_dep, \ + "libkmipclient", \ + "json-c/json.h", \ + "json-c-devel", \ + "HAVE_JSONC=0") + $(call check_dep, \ + "libkmipclient", \ + "libxml/tree.h", \ + "libxml2-devel", \ + "HAVE_LIBXML2=0", \ + `xml2-config --cflags` `xml2-config --libs`) + $(call check_dep, \ + "libkmipclient", \ + "curl/curl.h", \ + "libcurl-devel", \ + "HAVE_LIBCURL=0" \ + `curl-config --cflags` `curl-config --libs`) + curl-config --ssl-backends | grep OpenSSL >/dev/null 2>&1 || { echo "Error: libcurl is not built with the OpenSSL backend"; exit 1; } + touch check-dep-libkmipclient + +skip-libkmipclient-openssl: + echo " SKIP libkmipclient due to HAVE_OPENSSL=0" + +skip-libkmipclient-jsonc: + echo " SKIP libkmipclient due to HAVE_JSONC=0" + +skip-libkmipclient-xml: + echo " SKIP libkmipclient due to HAVE_LIBXML2=0" + +skip-libkmipclient-curl: + echo " SKIP libkmipclient due to HAVE_LIBCURL=0" + +all: $(BUILD_TARGETS) + +kmip.o: check-dep-libkmipclient kmip.c kmip.h utils.h $(rootdir)include/kmipclient/kmipclient.h +request.o: check-dep-libkmipclient request.c kmip.h names.h $(rootdir)include/kmipclient/kmipclient.h +response.o: check-dep-libkmipclient response.c kmip.h names.h $(rootdir)include/kmipclient/kmipclient.h +attribute.o: check-dep-libkmipclient attribute.c kmip.h names.h $(rootdir)include/kmipclient/kmipclient.h +key.o: check-dep-libkmipclient key.c kmip.h names.h $(rootdir)include/kmipclient/kmipclient.h +ttlv.o: check-dep-libkmipclient ttlv.c kmip.h utils.h $(rootdir)include/kmipclient/kmipclient.h +json.o: check-dep-libkmipclient json.c kmip.h names.h utils.h $(rootdir)include/kmipclient/kmipclient.h +xml.o: check-dep-libkmipclient xml.c kmip.h names.h utils.h $(rootdir)include/kmipclient/kmipclient.h +https.o: check-dep-libkmipclient https.c kmip.h utils.h $(rootdir)include/kmipclient/kmipclient.h +tls.o: check-dep-libkmipclient tls.c kmip.h utils.h $(rootdir)include/kmipclient/kmipclient.h +names.o: check-dep-libkmipclient names.c names.h utils.h $(rootdir)include/kmipclient/kmipclient.h +utils.o: check-dep-libkmipclient utils.c names.h utils.h $(rootdir)include/kmipclient/kmipclient.h + +libkmipclient.so.$(VERSION): ALL_CFLAGS += -fPIC `xml2-config --cflags` `curl-config --cflags` +libkmipclient.so.$(VERSION): LDLIBS = -ljson-c -lcrypto -lssl `xml2-config --libs` `curl-config --libs` +libkmipclient.so.$(VERSION): ALL_LDFLAGS += -shared -Wl,--version-script=libkmipclient.map \ + -Wl,-z,defs,-Bsymbolic -Wl,-soname,libkmipclient.so.$(VERM) +libkmipclient.so.$(VERSION): kmip.o request.o response.o attribute.o key.o ttlv.o json.o \ + xml.o https.o tls.o names.o utils.o + $(LINK) $(ALL_LDFLAGS) $^ $(LDLIBS) -o $@ + ln -srf libkmipclient.so.$(VERSION) libkmipclient.so.$(VERM) + ln -srf libkmipclient.so.$(VERSION) libkmipclient.so + +install-libkmipclient.so.$(VERSION): libkmipclient.so.$(VERSION) + $(INSTALL) -g $(GROUP) -o $(OWNER) -m 755 -T libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERSION) + ln -srf $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERM) + ln -srf $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so.$(VERSION) $(DESTDIR)$(SOINSTALLDIR)/libkmipclient.so + $(INSTALL) -d -m 770 $(DESTDIR)$(USRINCLUDEDIR)/kmipclient + $(INSTALL) -g $(GROUP) -o $(OWNER) -m 644 $(rootdir)include/kmipclient/kmipclient.h $(DESTDIR)$(USRINCLUDEDIR)/kmipclient + +install: all $(INSTALL_TARGETS) + +clean: + rm -f *.o libkmipclient.so* check-dep-libkmipclient detect-openssl-version.dep + +.PHONY: all install clean skip-libkmipclient-openssl skip-libkmipclient-jsonc \ + skip-libkmipclient-xml skip-libkmipclient-curl install-libkmipclient.so.$(VERSION) diff --git a/libkmipclient/attribute.c b/libkmipclient/attribute.c new file mode 100644 index 00000000..e0223dc5 --- /dev/null +++ b/libkmipclient/attribute.c @@ -0,0 +1,4011 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include +#include +#include +#include + +#include "kmip.h" +#include "names.h" + +/** + * Constructs a Template Attribute node (KMIP v1.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Template-Attribute Yes Structure v1.x only + * Name No Structure v1.x only + * ... may be repeated + * Attribute No Structure v1.x only + * ... may be repeated + * + * Also applies to Common Template-Attribute, Private Key Template-Attribute, + * Public Key Template-Attribute. + * + * @param tag the template-attribute tag + * @param num_names the number of names in the array (can be 0) + * @param names array of name nodes + * @param num_attrs the number of attributes in the array (can be 0) + * @param attrs array of attribute nodes + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +static struct kmip_node *kmip_new_template_attribute_v1( + enum kmip_tag tag, + unsigned int num_names, + struct kmip_node **names, + unsigned int num_attrs, + struct kmip_node **attrs) +{ + struct kmip_node *tmpl; + unsigned int i; + int rc; + + if (num_names > 0 && names == NULL) + return NULL; + if (num_attrs > 0 && attrs == NULL) + return NULL; + + switch (tag) { + case KMIP_TAG_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_COMMON_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_PRIVATE_KEY_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_PUBLIC_KEY_TEMPLATE_ATTRIBUTE: + break; + default: + return NULL; + } + + tmpl = kmip_node_new_structure_va(KMIP_TAG_TEMPLATE_ATTRIBUTE, NULL, 0); + if (tmpl == NULL) + return NULL; + + for (i = 0; i < num_names; i++) { + rc = kmip_node_add_structure_element(tmpl, names[i]); + if (rc != 0) + goto error; + } + + for (i = 0; i < num_attrs; i++) { + rc = kmip_node_add_structure_element(tmpl, attrs[i]); + if (rc != 0) + goto error; + } + + return tmpl; + +error: + kmip_node_free(tmpl); + return NULL; +} + +/** + * Gets information from a Template Attribute node (KMIP v1.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Template-Attribute Yes Structure v1.x only + * Name No Structure v1.x only + * ... may be repeated + * Attribute No Structure v1.x only + * ... may be repeated + * + * Also applies to Common Template-Attribute, Private Key Template-Attribute, + * Public Key Template-Attribute. + * + * @param node the KMIP node + * @param num_names On return: The number of names (can be NULL) + * @param name_index the index of the name item to return + * @param name On return: the name item of the specified index. + * Function returns -ENOENT if no name is available. + * Can be NULL, then no name entry is returned. + * @param num_attrs On return: The number of attributes (can be NULL) + * @param attr_index the index of the attribute item to return + * @param attr On return: the attribute item of the specified + * index. Function returns -ENOENT if no attribute is + * available. Can be NULL, then no attribute entry is + * returned. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +static int kmip_get_template_attribute_v1(const struct kmip_node *node, + unsigned int *num_names, + unsigned int name_index, + struct kmip_node **name, + unsigned int *num_attrs, + unsigned int attr_index, + struct kmip_node **attr) +{ + if (node == NULL) + return -EINVAL; + + switch (kmip_node_get_tag(node)) { + case KMIP_TAG_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_COMMON_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_PRIVATE_KEY_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_PUBLIC_KEY_TEMPLATE_ATTRIBUTE: + break; + default: + return -EBADMSG; + } + + if (num_names != NULL) + *num_names = kmip_node_get_structure_element_by_tag_count( + node, KMIP_TAG_NAME); + + if (name != NULL) { + *name = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_NAME, name_index); + if (*name == NULL) + return -ENOENT; + } + + if (num_attrs != NULL) + *num_attrs = kmip_node_get_structure_element_by_tag_count( + node, KMIP_TAG_ATTRIBUTE); + + if (attr != NULL) { + *attr = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE, attr_index); + if (*attr == NULL) { + if (name != NULL && *name != NULL) { + kmip_node_free(*name); + *name = NULL; + } + return -ENOENT; + } + } + + return 0; +} + +/** + * Constructs an Attribute node (KMIP v1.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Yes Structure v1.x only + * Attribute Name Yes Text String v1.x only + * Attribute Index No Integer v1.x only + * Attribute Value Yes v1.x only + * + * @param name the name of the attribute + * @param index the index of the attribute. If < 0 then this field + * is omitted + * @param value the attribute value node + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +static struct kmip_node *kmip_new_attribute_v1(const char *name, int32_t index, + struct kmip_node *value) +{ + struct kmip_node *attr = NULL, *nam, *idx = NULL; + + if (name == NULL || value == NULL) + return NULL; + + nam = kmip_node_new_text_string(KMIP_TAG_ATTRIBUTE_NAME, NULL, name); + + if (index >= 0) + idx = kmip_node_new_integer(KMIP_TAG_ATTRIBUTE_INDEX, NULL, + index); + + if (nam == NULL || (index >= 0 && idx == NULL)) + goto out; + + attr = kmip_node_new_structure_va(KMIP_TAG_ATTRIBUTE, NULL, 3, nam, idx, + value); + +out: + kmip_node_free(nam); + kmip_node_free(idx); + + return attr; +} + +/** + * Gets the information from an Attribute node (KMIP v1.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Yes Structure v1.x only + * Attribute Name Yes Text String v1.x only + * Attribute Index No Integer v1.x only + * Attribute Value Yes v1.x only + * + * @param node the KMIP node + * @param name On return: the attribute name (can be NULL) + * @param index On return: the attribute index (can be NULL) + * @param value On return: the attribute value (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +static int kmip_get_attribute_v1(const struct kmip_node *node, + const char **name, int32_t *index, + struct kmip_node **value) +{ + struct kmip_node *nam, *idx, *val; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_ATTRIBUTE) + return -EBADMSG; + + nam = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE_NAME, + 0); + idx = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE_INDEX, + 0); + val = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE_VALUE, + 0); + if (nam == NULL || val == NULL) { + rc = -EBADMSG; + goto out; + } + + if (name != NULL) + *name = kmip_node_get_text_string(nam); + if (index != NULL) + *index = (idx != NULL ? kmip_node_get_integer(idx) : 0); + if (value != NULL) + *value = val; + +out: + kmip_node_free(nam); + kmip_node_free(idx); + if (value == NULL || rc != 0) + kmip_node_free(val); + + return rc; +} + +/** + * Constructs a (Vendor) Attribute node (KMIP v2.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Yes Structure v2.x only + * Vendor Identification Yes Text String v2.x only + * Attribute Name Yes Text String v2.x only + * Attribute Value Yes v2.x only + * + * @param vendor_id the vendor identification of the attribute + * @param name the name of the attribute + * @param value the attribute value node + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_vendor_attribute(const char *vendor_id, + const char *name, + struct kmip_node *value) +{ + struct kmip_node *attr = NULL, *nam, *vend = NULL; + + if (vendor_id == NULL || name == NULL || value == NULL) + return NULL; + + vend = kmip_node_new_text_string(KMIP_TAG_VENDOR_IDENTIFICATION, NULL, + vendor_id); + nam = kmip_node_new_text_string(KMIP_TAG_ATTRIBUTE_NAME, NULL, name); + if (nam == NULL || vend == NULL) + goto out; + + attr = kmip_node_new_structure_va(KMIP_TAG_ATTRIBUTE, NULL, 3, vend, + nam, value); + +out: + kmip_node_free(nam); + kmip_node_free(vend); + + return attr; +} + +/** + * Gets the information from a (Vendor) Attribute node (KMIP v2.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Yes Structure v2.x only + * Vendor Identification Yes Text String v2.x only + * Attribute Name Yes Text String v2.x only + * Attribute Value Yes v2.x only + * + * @param node the KMIP node + * @param vendor_id On return: the vendor identification (can be NULL) + * @param name On return: the attribute name (can be NULL) + * @param value On return: the attribute value (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_vendor_attribute(const struct kmip_node *node, + const char **vendor_id, const char **name, + struct kmip_node **value) +{ + struct kmip_node *vend, *nam, *val; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_ATTRIBUTE) + return -EBADMSG; + + vend = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_VENDOR_IDENTIFICATION, 0); + nam = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE_NAME, + 0); + val = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE_VALUE, + 0); + if (vend == NULL || nam == NULL || val == NULL) { + rc = -EBADMSG; + goto out; + } + + if (vendor_id != NULL) + *vendor_id = kmip_node_get_text_string(vend); + if (name != NULL) + *name = kmip_node_get_text_string(nam); + if (value != NULL) + *value = val; + +out: + kmip_node_free(vend); + kmip_node_free(nam); + if (value == NULL || rc != 0) + kmip_node_free(val); + + return rc; +} + +/** + * Constructs an Attributes node (KMIP v2.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attributes Yes Structure v2.x only + * No v2.x only + * ... may be repeated + * + * Also applies to Common Attributes, Private Key Attributes, + * Public Key Attributes + * + * @param tag the attributes tag + * @param attrs_count the number of attributes following (can be 0) + * @param attrs the array of attributes + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +static struct kmip_node *kmip_new_attributes_v2(enum kmip_tag tag, + unsigned int attrs_count, + struct kmip_node **attrs) +{ + switch (tag) { + case KMIP_TAG_ATTRIBUTES: + case KMIP_TAG_COMMON_ATTRIBUTES: + case KMIP_TAG_PRIVATE_KEY_ATTRIBUTES: + case KMIP_TAG_PUBLIC_KEY_ATTRIBUTES: + break; + default: + return NULL; + } + + return kmip_node_new_structure(KMIP_TAG_ATTRIBUTES, NULL, attrs_count, + attrs); + +} + +/** + * Gets the information from an Attributes node (KMIP v2.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attributes Yes Structure v2.x only + * No v2.x only + * ... may be repeated + * + * Also applies to Common Attributes, Private Key Attributes, + * Public Key Attributes + * + * @param node the KMIP node + * @param num_attrs On return: The number of attributes (can be NULL) + * @param attr_index the index of the attribute to return + * @param value On return: the attribute item of the specified + * index. Function returns -ENOENT if no attribute is + * available. Can be NULL, then no attribute entry is + * returned. + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +static int kmip_get_attributes_v2(const struct kmip_node *node, + unsigned int *num_attrs, + unsigned int attr_index, + struct kmip_node **attr) +{ + if (node == NULL) + return -EINVAL; + + switch (kmip_node_get_tag(node)) { + case KMIP_TAG_ATTRIBUTES: + case KMIP_TAG_COMMON_ATTRIBUTES: + case KMIP_TAG_PRIVATE_KEY_ATTRIBUTES: + case KMIP_TAG_PUBLIC_KEY_ATTRIBUTES: + break; + default: + return -EBADMSG; + } + + if (num_attrs != NULL) + *num_attrs = kmip_node_get_structure_element_count(node); + + if (attr == NULL) + return 0; + + *attr = kmip_node_get_structure_element_by_index(node, attr_index); + if (*attr == NULL) + return -ENOENT; + + return 0; +} + +/** + * Split a KMIP v1.x custom attribute name into a vendor-id and attribute + * name for a KMIP v2.x vendor attribute. + * + * @param name the custom attribute name. This string is being + * modified during splitting. If the contents is still + * needed, the caller should copy it first. + * @param vendor_id On return: the vendor-ID string. This point to + * inside the passed name string from the 1st argument. + * @param attr_name On return: the vendor attribute name string. + * This point to inside the passed name string from + * the 1st argument. + * + * @returns 0 on success, or a negative errno in case of an error + */ +static int kmip_split_v1_custom_attr_name(char *name, char **vendor_id, + char **attr_name) +{ + char *tok; + + if (name == NULL || vendor_id == NULL || attr_name == NULL) + return -EINVAL; + + /* + * KMIP v1.x custom attribute names in the form 'x|y--' + * are transformed into a KMIP v2.x vendor attribute with vendor id + * and name . If no vendor id is found, then the vendor + * id is set to 'x' or 'y', and the name is the remaining name string. + */ + if (strncmp(name, "x-", 2) != 0 && strncmp(name, "y-", 2) != 0) + return -EBADMSG; + + name[1] = 0; + tok = strchr(name + 2, '-'); + if (tok != NULL) { + *tok = 0; + *vendor_id = name + 2; + *attr_name = tok + 1; + } else { + *vendor_id = name; + *attr_name = name + 2; + } + + return 0; +} + +/** + * Builds a KMIP v1.x custom attribute name from a KMIP v2.x vendor-id and + * attribute name. + * + * @param vendor_id the vendor-ID string + * @param attr_name the vendor attribute name string + * + * @returns a newly allocated custom attribute name string, or NULL in case of + * an error. The returned string must be freed by the caller. + */ +char *kmip_build_v1_custom_attr_name(const char *vendor_id, + const char *attr_name) +{ + char *custom_name = NULL; + int rc; + + if (vendor_id == NULL || attr_name == NULL) + return NULL; + + if (strcmp(vendor_id, "x") == 0 || + strcmp(vendor_id, "y") == 0) + rc = asprintf(&custom_name, "%s-%s", + vendor_id, attr_name); + else + rc = asprintf(&custom_name, "x-%s-%s", + vendor_id, attr_name); + + if (rc <= 0 || custom_name == NULL) + return NULL; + + return custom_name; +} + +/** + * Converts a KMIP v1.x Attribute into a KMIP v2.x Attribute + * + * @param v1_attr the KMIP v1.x attribute to convert + * @param v2_attr On return: the KMIP v2.x attribute + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_v2_attr_from_v1_attr(struct kmip_node *v1_attr, + struct kmip_node **v2_attr) +{ + char *copy, *vendor_id, *attr_name; + struct kmip_node *value, *cloned_value; + enum kmip_tag v2_tag; + const char *name; + int rc; + + if (v1_attr == NULL || v2_attr == NULL) + return -EINVAL; + + rc = kmip_get_attribute_v1(v1_attr, &name, NULL, &value); + if (rc != 0) + return rc; + + if (strncmp(name, "x-", 2) == 0 || + strncmp(name, "y-", 2) == 0) { + /* Special handling for Custom Attribute */ + copy = strdup(name); + if (copy == NULL) { + kmip_node_free(value); + return -ENOMEM; + } + + rc = kmip_split_v1_custom_attr_name(copy, &vendor_id, + &attr_name); + if (rc != 0) { + kmip_node_free(value); + free(copy); + return rc; + } + + cloned_value = kmip_node_clone(value); + kmip_node_free(value); + if (cloned_value == NULL) { + free(copy); + return -ENOMEM; + } + *v2_attr = kmip_new_vendor_attribute(vendor_id, attr_name, + cloned_value); + free(copy); + kmip_node_free(cloned_value); + return 0; + } + + v2_tag = kmip_attr_tag_by_v1_attr_name(name); + if (v2_tag == 0) { + kmip_node_free(value); + return -EBADMSG; + } + + cloned_value = kmip_node_clone(value); + kmip_node_free(value); + if (cloned_value == NULL) + return -ENOMEM; + + cloned_value->tag = v2_tag; + *v2_attr = cloned_value; + + return 0; +} + +/** + * Converts a KMIP v2.x Attribute into a KMIP v1.x Attribute + * + * @param v2_attr the KMIP v2.x attribute to convert + * @param v1_attr On return: the KMIP v1.x attribute + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_v1_attr_from_v2_attr(struct kmip_node *v2_attr, + struct kmip_node **v1_attr) +{ + struct kmip_node *attr_value, *cloned_value; + const char *attr_name, *vendor_id; + char *custom_name; + int rc; + + if (v2_attr == NULL || v1_attr == NULL) + return -EINVAL; + + if (v2_attr->tag == KMIP_TAG_ATTRIBUTE) { + /* Special handling for v2.x Vendor Attribute */ + rc = kmip_get_vendor_attribute(v2_attr, &vendor_id, + &attr_name, &attr_value); + if (rc != 0) + return rc; + + custom_name = kmip_build_v1_custom_attr_name(vendor_id, + attr_name); + if (custom_name == NULL) { + kmip_node_free(attr_value); + return -EBADMSG; + } + + cloned_value = kmip_node_clone(attr_value); + kmip_node_free(attr_value); + if (cloned_value == NULL) { + free(custom_name); + return -ENOMEM; + } + + *v1_attr = kmip_new_attribute_v1(custom_name, -1, cloned_value); + kmip_node_free(cloned_value); + free(custom_name); + if (*v1_attr == NULL) + return -ENOMEM; + + return 0; + } + + attr_name = kmip_v1_attr_name_by_tag(v2_attr->tag); + if (attr_name == NULL) + return -EBADMSG; + + cloned_value = kmip_node_clone(v2_attr); + if (cloned_value == NULL) + return -ENOMEM; + + /* Modify the cloned v2 attr and use it as value of the v1 attr */ + cloned_value->tag = KMIP_TAG_ATTRIBUTE_VALUE; + *v1_attr = kmip_new_attribute_v1(attr_name, -1, cloned_value); + kmip_node_free(cloned_value); + if (*v1_attr == NULL) + return -ENOMEM; + + return 0; +} + +/** + * Constructs an Attributes node (KMIP v2.x) or a Template Attribute node + * (KMIP v1.x) from a list of attributes in KMIP v2.x style, dependent on the + * protocol version specified: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attributes Yes Structure v2.x only + * No v2.x only + * ... may be repeated + * + * Also applies to Common Attributes, Private Key Attributes, + * Public Key Attributes + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Template-Attribute Yes Structure v1.x only + * Name No Structure v1.x only + * ... may be repeated + * Attribute No Structure v1.x only + * ... may be repeated + * + * Also applies to Common Template-Attribute, Private Key Template-Attribute, + * Public Key Template-Attribute. + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param v2_tag the attributes tag + * @param attrs_count the number of attributes following + * @param v2_attrs the array of attributes (as KMIP v2.x attributes) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_attributes(const struct kmip_version *version, + enum kmip_tag v2_tag, + unsigned int attrs_count, + struct kmip_node **v2_attrs) +{ + struct kmip_node *attrs = NULL, *attr; + struct kmip_node **v1_attrs = NULL; + enum kmip_tag v1_tag = 0; + unsigned int i; + int rc; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + if (version->major == 1) { + /* KMIP v1.x: translate v1-tag to v2-tag */ + switch (v2_tag) { + case KMIP_TAG_ATTRIBUTES: + v1_tag = KMIP_TAG_TEMPLATE_ATTRIBUTE; + break; + case KMIP_TAG_COMMON_ATTRIBUTES: + v1_tag = KMIP_TAG_COMMON_TEMPLATE_ATTRIBUTE; + break; + case KMIP_TAG_PRIVATE_KEY_ATTRIBUTES: + v1_tag = KMIP_TAG_PRIVATE_KEY_TEMPLATE_ATTRIBUTE; + break; + case KMIP_TAG_PUBLIC_KEY_ATTRIBUTES: + v1_tag = KMIP_TAG_PUBLIC_KEY_TEMPLATE_ATTRIBUTE; + break; + default: + return NULL; + } + + if (attrs_count > 0) { + v1_attrs = calloc(attrs_count, + sizeof(struct kmip_node *)); + if (v1_attrs == NULL) + return NULL; + } + + for (i = 0; i < attrs_count; i++) { + attr = v2_attrs[i]; + if (attr == NULL) + goto error; + + rc = kmip_v1_attr_from_v2_attr(attr, &v1_attrs[i]); + if (rc != 0) + goto error; + } + + attrs = kmip_new_template_attribute_v1(v1_tag, 0, NULL, + attrs_count, v1_attrs); + +error: + for (i = 0; i < attrs_count; i++) { + if (v1_attrs[i] == NULL) + continue; + kmip_node_free(v1_attrs[i]); + } + if (v1_attrs != NULL) + free(v1_attrs); + } else { + /* KMIP >= v2.0 */ + attrs = kmip_new_attributes_v2(v2_tag, attrs_count, v2_attrs); + } + + return attrs; +} + +/** + * Constructs an Attributes node (KMIP v2.x) or a Template Attribute node + * (KMIP v1.x) from a list of attributes in KMIP v2.x style, dependent on the + * protocol version specified: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attributes Yes Structure v2.x only + * No v2.x only + * ... may be repeated + * + * Also applies to Common Attributes, Private Key Attributes, + * Public Key Attributes + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Template-Attribute Yes Structure v1.x only + * Name No Structure v1.x only + * ... may be repeated + * Attribute No Structure v1.x only + * ... may be repeated + * + * Also applies to Common Template-Attribute, Private Key Template-Attribute, + * Public Key Template-Attribute. + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param v2_tag the attributes tag + * @param attrs_count the number of attributes following + * @param the attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_attributes_va(const struct kmip_version *version, + enum kmip_tag v2_tag, + unsigned int attrs_count, ...) +{ + struct kmip_node *ret, **attrs = NULL; + unsigned int i, k; + va_list ap; + + if (attrs_count > 0) { + attrs = calloc(attrs_count, sizeof(struct kmip_node *)); + if (attrs == NULL) + return NULL; + } + + va_start(ap, attrs_count); + for (i = 0, k = 0; i < attrs_count; i++) { + attrs[k] = va_arg(ap, struct kmip_node *); + if (attrs[k] != NULL) + k++; + } + va_end(ap); + + ret = kmip_new_attributes(version, v2_tag, k, attrs); + if (attrs != NULL) + free(attrs); + + return ret; +} + +/** + * Gets the information from an Attributes node (KMIP v2.x) or a Template + * Attribute node (KMIP v1.x). The returned attribute is always in KMIP v2.x + * style. + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attributes Yes Structure v2.x only + * No v2.x only + * ... may be repeated + * + * Also applies to Common Attributes, Private Key Attributes, + * Public Key Attributes + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Template-Attribute Yes Structure v1.x only + * Name No Structure v1.x only + * ... may be repeated + * Attribute No Structure v1.x only + * ... may be repeated + * + * Also applies to Common Template-Attribute, Private Key Template-Attribute, + * Public Key Template-Attribute. + * + * @param node the KMIP node + * @param num_attrs On return: the number of attributes (can be NULL). + * @param attr_index the index of the attribute to return + * @param value On return: the attribute item of the specified index + * (as a KMIP v2.x attribute). + * Function returns -ENOENT if no attribute is + * available. Can be NULL, then no attribute entry is + * returned. + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_attributes(const struct kmip_node *node, unsigned int *num_attrs, + unsigned int attr_index, struct kmip_node **attr) +{ + struct kmip_node *v1_attr, *v2_attr; + int rc; + + if (node == NULL) + return -EINVAL; + + switch (kmip_node_get_tag(node)) { + case KMIP_TAG_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_COMMON_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_PRIVATE_KEY_TEMPLATE_ATTRIBUTE: + case KMIP_TAG_PUBLIC_KEY_TEMPLATE_ATTRIBUTE: + /* KMIP v1.x template attributes */ + if (attr == NULL) { + rc = kmip_get_template_attribute_v1(node, NULL, 0, NULL, + num_attrs, 0, NULL); + return rc; + } + + rc = kmip_get_template_attribute_v1(node, NULL, 0, NULL, + num_attrs, attr_index, + &v1_attr); + if (rc != 0) + return rc; + + rc = kmip_v2_attr_from_v1_attr(v1_attr, &v2_attr); + kmip_node_free(v1_attr); + if (rc != 0) + return rc; + + *attr = v2_attr; + break; + + case KMIP_TAG_ATTRIBUTES: + case KMIP_TAG_COMMON_ATTRIBUTES: + case KMIP_TAG_PRIVATE_KEY_ATTRIBUTES: + case KMIP_TAG_PUBLIC_KEY_ATTRIBUTES: + /* KMIP v2.x attributes */ + rc = kmip_get_attributes_v2(node, num_attrs, attr_index, attr); + if (rc != 0) + return rc; + break; + + default: + return -EBADMSG; + } + + return 0; +} + +/** + * Constructs an Attribute Reference node (KMIP v2.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Reference Yes Enumeration v2.x only + * or + * Attribute Reference Yes Structure v2.x only + * Vendor Identification Yes Text String v2.x only + * Attribute Name Yes Text String v2.x only + * + * @param attr_tag the attribute tag + * @param vendor_id the vendor identification of the attribute + * @param name the name of the attribute + * + * Either the attr_tag or the vendor_id and name can be specified, but not both. + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_attribute_reference(enum kmip_tag attr_tag, + const char *vendor_id, + const char *name) +{ + struct kmip_node *ref = NULL, *nam, *vend = NULL; + + if (attr_tag == 0 && (vendor_id == NULL || name == NULL)) + return NULL; + if (attr_tag != 0 && (vendor_id != NULL || name != NULL)) + return NULL; + + if (attr_tag != 0) + return kmip_node_new_enumeration(KMIP_TAG_ATTRIBUTE_REFERENCE, + NULL, attr_tag); + + vend = kmip_node_new_text_string(KMIP_TAG_VENDOR_IDENTIFICATION, NULL, + vendor_id); + nam = kmip_node_new_text_string(KMIP_TAG_ATTRIBUTE_NAME, NULL, name); + if (nam == NULL || vend == NULL) + goto out; + + ref = kmip_node_new_structure_va(KMIP_TAG_ATTRIBUTE_REFERENCE, NULL, + 2, vend, nam); + +out: + kmip_node_free(nam); + kmip_node_free(vend); + + return ref; +} + +/** + * Gets the information from a Attribute Reference node (KMIP v2.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Reference Yes Enumeration v2.x only + * or + * Attribute Reference Yes Structure v2.x only + * Vendor Identification Yes Text String v2.x only + * Attribute Name Yes Text String v2.x only + * + * @param node the KMIP node + * @param attr_tag On return: The attribute tag (can be NULL) + * @param vendor_id On return: the vendor identification (can be NULL) + * @param name On return: the attribute name (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_attribute_reference(const struct kmip_node *node, + enum kmip_tag *attr_tag, + const char **vendor_id, const char **name) +{ + struct kmip_node *vend, *nam; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_ATTRIBUTE_REFERENCE) + return -EBADMSG; + + if (kmip_node_get_type(node) == KMIP_TYPE_ENUMERATION) { + if (attr_tag != NULL) + *attr_tag = kmip_node_get_enumeration(node); + + if (vendor_id != NULL) + vendor_id = NULL; + if (name != NULL) + *name = NULL; + + return 0; + } + + if (kmip_node_get_type(node) != KMIP_TYPE_STRUCTURE) + return -EBADMSG; + + if (attr_tag != NULL) + *attr_tag = 0; + + vend = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_VENDOR_IDENTIFICATION, 0); + nam = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE_NAME, 0); + if (vend == NULL || nam == NULL) { + rc = -EBADMSG; + goto out; + } + + if (vendor_id != NULL) + *vendor_id = kmip_node_get_text_string(vend); + if (name != NULL) + *name = kmip_node_get_text_string(nam); + +out: + kmip_node_free(vend); + kmip_node_free(nam); + + return rc; +} + +/** + * Constructs an Current or New Attribute node (KMIP v2.x): + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Current Attribute Yes Structure v2.x only + * or + * New Attribute Yes Structure v2.x only + * + * @param new_attr if true a New Attribute structure, if false a + * Current Attribute structure is created + * @param attr the KMIP v2.x attribute + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_current_new_attribute(bool new_attr, + struct kmip_node *attr) +{ + enum kmip_tag tag; + + if (attr == NULL) + return NULL; + + tag = (new_attr ? KMIP_TAG_NEW_ATTRIBUTE : KMIP_TAG_CURRENT_ATTRIBUTE); + return kmip_node_new_structure_va(tag, NULL, 1, attr); +} + +/** + * Constructs an Attribute Name node (KMIP v1.x) from a KMIP v2.x Attribute + * Reference: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Name Yes Text String v1.x only + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Reference Yes Enumeration v2.x only + * or + * Attribute Reference Yes Structure v2.x only + * Vendor Identification Yes Text String v2.x only + * Attribute Name Yes Text String v2.x only + * + * @param v2_attr_ref the attribute reference node (as of KMIP v2.x) + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_attribute_name_v1( + const struct kmip_node *v2_attr_ref) +{ + const char *vendor_id = NULL, *attr_name = NULL; + enum kmip_tag attr_tag = 0; + struct kmip_node *ret; + char *name = NULL; + int rc; + + rc = kmip_get_attribute_reference(v2_attr_ref, &attr_tag, &vendor_id, + &attr_name); + if (rc != 0) + return NULL; + + if (attr_tag != 0) { + attr_name = kmip_v1_attr_name_by_tag(attr_tag); + if (attr_name == NULL) + return NULL; + + return kmip_node_new_text_string(KMIP_TAG_ATTRIBUTE_NAME, NULL, + attr_name); + } + + if (vendor_id == NULL || attr_name == NULL) + return NULL; + + /* Special handling for v2.x Vendor Attribute */ + name = kmip_build_v1_custom_attr_name(vendor_id, attr_name); + if (name == NULL) + return NULL; + + ret = kmip_node_new_text_string(KMIP_TAG_ATTRIBUTE_NAME, NULL, name); + free(name); + return ret; +} + +/** + * Gets the information from an Attribute Name node (KMIP v1.x) and returns + * a KMIP v2.x Attribute Reference: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Name Yes Text String v1.x only + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Attribute Reference Yes Enumeration v2.x only + * or + * Attribute Reference Yes Structure v2.x only + * Vendor Identification Yes Text String v2.x only + * Attribute Name Yes Text String v2.x only + * + * @param node the KMIP node + * @param v2_attr_ref On return: the attribute reference node (as of + * KMIP v2.x) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_attribute_name_v1(const struct kmip_node *node, + struct kmip_node **v2_attr_ref) +{ + char *copy, *vendor_id, *attr_name; + enum kmip_tag attr_tag; + const char *name; + int rc; + + if (node == NULL || v2_attr_ref == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_ATTRIBUTE_NAME) + return -EBADMSG; + + name = kmip_node_get_text_string(node); + if (name == NULL) + return -EBADMSG; + + if (strncmp(name, "x-", 2) == 0 || strncmp(name, "y-", 2) == 0) { + /* Special handling for Custom Attribute */ + copy = strdup(name); + if (copy == NULL) + return -ENOMEM; + + rc = kmip_split_v1_custom_attr_name(copy, &vendor_id, + &attr_name); + if (rc != 0) { + free(copy); + return rc; + } + + *v2_attr_ref = kmip_new_attribute_reference(0, vendor_id, + attr_name); + free(copy); + + if (*v2_attr_ref == NULL) + return -ENOMEM; + + return 0; + } + + attr_tag = kmip_attr_tag_by_v1_attr_name(name); + if (attr_tag == 0) + return -EBADMSG; + + *v2_attr_ref = kmip_new_attribute_reference(attr_tag, NULL, NULL); + if (*v2_attr_ref == NULL) + return -ENOMEM; + + return 0; +} + +/** + * Constructs a Unique Identifier attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param text_id the unique identifier as text string (or NULL) + * @param enum_id the unique identifier as enumeration (or 0) + * @param int_id the unique identifier as integer + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_unique_identifier(const char *text_id, + enum kmip_unique_identifier enum_id, + int32_t int_id) +{ + if (text_id != NULL && enum_id != 0) + return NULL; + + if (text_id != NULL) + return kmip_node_new_text_string(KMIP_TAG_UNIQUE_IDENTIFIER, + NULL, text_id); + if (enum_id != 0) + return kmip_node_new_enumeration(KMIP_TAG_UNIQUE_IDENTIFIER, + NULL, enum_id); + + return kmip_node_new_integer(KMIP_TAG_UNIQUE_IDENTIFIER, NULL, int_id); +} + +/** + * Gets the information from a Unique Identifier attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param text_id the unique identifier as text string (can be NULL) + * @param enum_id the unique identifier as enumeration (can be NULL) + * @param int_id the unique identifier as integer (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_unique_identifier(const struct kmip_node *node, + const char **text_id, + enum kmip_unique_identifier *enum_id, + int32_t *int_id) +{ + if (node == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_UNIQUE_IDENTIFIER) + return -EBADMSG; + + if (text_id != NULL) { + if (kmip_node_get_type(node) == KMIP_TYPE_TEXT_STRING) + *text_id = kmip_node_get_text_string(node); + else + *text_id = NULL; + } + + if (enum_id != NULL) { + if (kmip_node_get_type(node) == KMIP_TYPE_ENUMERATION) + *enum_id = kmip_node_get_enumeration(node); + else + *enum_id = 0; + } + + if (int_id != NULL) { + if (kmip_node_get_type(node) == KMIP_TYPE_INTEGER) + *int_id = kmip_node_get_integer(node); + else + *int_id = 0; + } + + return 0; +} + +/** + * Constructs a Name attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Name Yes Structure v1.0 + * Name Value Yes Text String v1.0 + * Name Type Yes Enumeration v1.0 + * + * @param value the value of the name + * @param type the type of the name + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_name(const char *value, enum kmip_name_type type) +{ + struct kmip_node *name = NULL, *val, *typ; + + if (value == NULL) + return NULL; + + val = kmip_node_new_text_string(KMIP_TAG_NAME_VALUE, NULL, value); + typ = kmip_node_new_enumeration(KMIP_TAG_NAME_TYPE, NULL, type); + + if (val == NULL || typ == NULL) + goto out; + + name = kmip_node_new_structure_va(KMIP_TAG_NAME, NULL, 2, val, typ); + +out: + kmip_node_free(val); + kmip_node_free(typ); + + return name; +} + +/** + * Gets the information from a Name attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Name Yes Structure v1.0 + * Name Value Yes Text String v1.0 + * Name Type Yes Enumeration v1.0 + * + * @param node the KMIP node + * @param value On return: the name value (can be NULL) + * @param type On return: the name type (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_name(const struct kmip_node *node, + const char **value, enum kmip_name_type *type) +{ + struct kmip_node *val, *typ; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_NAME) + return -EBADMSG; + + val = kmip_node_get_structure_element_by_tag(node, KMIP_TAG_NAME_VALUE, + 0); + typ = kmip_node_get_structure_element_by_tag(node, KMIP_TAG_NAME_TYPE, + 0); + if (val == NULL || typ == NULL) { + rc = -EBADMSG; + goto out; + } + + if (value != NULL) + *value = kmip_node_get_text_string(val); + if (type != NULL) + *type = kmip_node_get_enumeration(typ); + +out: + kmip_node_free(val); + kmip_node_free(typ); + + return rc; +} + +/** + * Constructs a Alternative Name attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Alternative Name Yes Structure v1.2 + * Alternative Name Value Yes Text String v1.2 + * Alternative Name Type Yes Enumeration v1.2 + * + * @param value the value of the alternative name + * @param type the type of the alternative name + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_alternative_name(const char *value, + enum kmip_alternative_name_type type) +{ + struct kmip_node *name = NULL, *val, *typ; + + if (value == NULL) + return NULL; + + val = kmip_node_new_text_string(KMIP_TAG_ALTERNATE_NAME_VALUE, NULL, + value); + typ = kmip_node_new_enumeration(KMIP_TAG_ALTERNATE_NAME_TYPE, NULL, + type); + + if (val == NULL || typ == NULL) + goto out; + + name = kmip_node_new_structure_va(KMIP_TAG_ALTERNATE_NAME, NULL, 2, val, + typ); + +out: + kmip_node_free(val); + kmip_node_free(typ); + + return name; +} + +/** + * Gets the information from an Alternative Name attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Alternative Name Yes Structure v1.2 + * Alternative Name Value Yes Text String v1.2 + * Alternative Name Type Yes Enumeration v1.2 + * + * @param node the KMIP node + * @param value On return: the alternative name value (can be NULL) + * @param type On return: the alternative name type (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_alternative_name(const struct kmip_node *node, + const char **value, + enum kmip_alternative_name_type *type) +{ + struct kmip_node *val, *typ; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_ALTERNATE_NAME) + return -EBADMSG; + + val = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ALTERNATE_NAME_VALUE, 0); + typ = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ALTERNATE_NAME_TYPE, 0); + if (val == NULL || typ == NULL) { + rc = -EBADMSG; + goto out; + } + + if (value != NULL) + *value = kmip_node_get_text_string(val); + if (type != NULL) + *type = kmip_node_get_enumeration(typ); + +out: + kmip_node_free(val); + kmip_node_free(typ); + + return rc; +} + +/** + * Constructs a Object Type attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Object Type Yes Enumeration v1.0 + * + * @param obj_type the object type + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_object_type(enum kmip_object_type obj_type) +{ + return kmip_node_new_enumeration(KMIP_TAG_OBJECT_TYPE, NULL, obj_type); +} + +/** + * Gets the information from a Object Type attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Object Type Yes Enumeration v1.0 + * + * + * @param node the KMIP node + * @param obj_type the object type + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_object_type(const struct kmip_node *node, + enum kmip_object_type *obj_type) +{ + if (node == NULL || obj_type == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_OBJECT_TYPE) + return -EBADMSG; + + *obj_type = kmip_node_get_enumeration(node); + return 0; +} + +/** + * Constructs a Cryptographic Algorithm attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Algorithm Yes Enumeration v1.0 + * + * @param algo the cryptographic algorithm + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_cryptographic_algorithm(enum kmip_crypto_algo algo) +{ + return kmip_node_new_enumeration(KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, NULL, + algo); +} + +/** + * Gets the information from a Cryptographic Algorithm attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Algorithm Yes Enumeration v1.0 + * + * + * @param node the KMIP node + * @param algo the cryptographic algorithm + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_cryptographic_algorithm(const struct kmip_node *node, + enum kmip_crypto_algo *algo) +{ + if (node == NULL || algo == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM) + return -EBADMSG; + + *algo = kmip_node_get_enumeration(node); + return 0; +} + +/** + * Constructs a Cryptographic Length attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Length Yes Integer v1.0 + * + * @param length the cryptographic length + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_cryptographic_length(int32_t length) +{ + return kmip_node_new_integer(KMIP_TAG_CRYPTOGRAPHIC_LENGTH, NULL, + length); +} + +/** + * Gets the information from a Cryptographic Length attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Length Yes Integer v1.0 + * + * + * @param node the KMIP node + * @param length the cryptographic length + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_cryptographic_length(const struct kmip_node *node, + int32_t *length) +{ + if (node == NULL || length == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_CRYPTOGRAPHIC_LENGTH) + return -EBADMSG; + + *length = kmip_node_get_integer(node); + return 0; +} + +/** + * Constructs a Certificate Type attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Certificate Type Yes Enumeration v1.0 + * + * @param type the certificate type + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_certificate_type(enum kmip_certificate_type type) +{ + return kmip_node_new_enumeration(KMIP_TAG_CERTIFICATE_TYPE, NULL, type); +} + +/** + * Gets the information from a Certificate Type attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Certificate Type Yes Enumeration v1.0 + * + * + * @param node the KMIP node + * @param type the certificate type + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_certificate_type(const struct kmip_node *node, + enum kmip_certificate_type *type) +{ + if (node == NULL || type == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_CERTIFICATE_TYPE) + return -EBADMSG; + + *type = kmip_node_get_enumeration(node); + return 0; +} + +/** + * Constructs a Cryptographic Usage Mask attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Usage Mask Yes Integer v1.0 + * + * @param usage_mask the cryptographic usage mask + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_cryptographic_usage_mask(int32_t usage_mask) +{ + return kmip_node_new_integer(KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK, NULL, + usage_mask); +} + +/** + * Gets the information from a Cryptographic Usage Mask attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Usage Mask Yes Integer v1.0 + * + * + * @param node the KMIP node + * @param usage_mask the cryptographic usage mask + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_cryptographic_usage_mask(const struct kmip_node *node, + int32_t *usage_mask) +{ + if (node == NULL || usage_mask == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK) + return -EBADMSG; + + *usage_mask = kmip_node_get_integer(node); + return 0; +} + +/** + * Constructs a State attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * State Yes Enumeration v1.0 + * + * @param state the state + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_state(enum kmip_state state) +{ + return kmip_node_new_enumeration(KMIP_TAG_STATE, NULL, state); +} + +/** + * Gets the information from a State attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * State Yes Enumeration v1.0 + * + * + * @param node the KMIP node + * @param state the state + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_state(const struct kmip_node *node, enum kmip_state *state) +{ + if (node == NULL || state == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_STATE) + return -EBADMSG; + + *state = kmip_node_get_enumeration(node); + return 0; +} + +/** + * Constructs a Initial Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Initial Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_initial_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_INITIAL_DATE, NULL, date); +} + +/** + * Gets the information from a Initial Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Initial Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_initial_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_INITIAL_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Activation Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Activation Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_activation_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_ACTIVATION_DATE, NULL, date); +} + +/** + * Gets the information from a Activation Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Activation Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_activation_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_ACTIVATION_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Deactivation Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Deactivation Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_deactivation_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_DEACTIVATION_DATE, NULL, + date); +} + +/** + * Gets the information from a Deactivation Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Deactivation Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_deactivation_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_DEACTIVATION_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Destroy Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Destroy Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_destroy_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_DESTROY_DATE, NULL, date); +} + +/** + * Gets the information from a Destroy Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Destroy Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_destroy_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_DESTROY_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Compromise Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Compromise Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_compromise_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_COMPROMIZE_DATE, NULL, date); +} + +/** + * Gets the information from a Compromise Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Compromise Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_compromise_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_COMPROMIZE_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Compromise Occurrence Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Compromise Occurrence Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_compromise_occurrence_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_COMPROMISE_OCCURRENCE_DATE, + NULL, date); +} + +/** + * Gets the information from a Compromise Occurrence Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Compromise Occurrence Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_compromise_occurrence_date(const struct kmip_node *node, + int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_COMPROMISE_OCCURRENCE_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Last Change Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Last Change Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_last_change_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_LAST_CHANGE_DATE, NULL, date); +} + +/** + * Gets the information from a Last Change Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Last Change Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_last_change_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_LAST_CHANGE_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Original Creation Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Original Creation Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_original_creation_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_ORIGINAL_CREATION_DATE, NULL, + date); +} + +/** + * Gets the information from a Original Creation Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Original Creation Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_original_creation_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_ORIGINAL_CREATION_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Archive Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Archive Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_archive_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_ARCHIVE_DATE, NULL, date); +} + +/** + * Gets the information from a Archive Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Archive Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_archive_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_ARCHIVE_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Process Start Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Process Start Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_process_start_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_PROCESS_START_DATE, NULL, + date); +} + +/** + * Gets the information from a Process Start Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Process Start Date Yes Date-Time v1.0 + * + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_process_start_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_PROCESS_START_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Protect Stop Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protect Stop Date Yes Date-Time v1.0 + * + * @param date the date + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_protect_stop_date(int64_t date) +{ + return kmip_node_new_enumeration(KMIP_TAG_PROTECT_STOP_DATE, NULL, + date); +} + +/** + * Gets the information from a Protect Stop Date attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protect Stop Date Yes Date-Time v1.0 + * + * @param node the KMIP node + * @param date the date + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_protect_stop_date(const struct kmip_node *node, int64_t *date) +{ + if (node == NULL || date == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_PROTECT_STOP_DATE) + return -EBADMSG; + + *date = kmip_node_get_date_time(node); + return 0; +} + +/** + * Constructs a Cryptographic Parameters attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Parameters Structure v1.0 + * Block Cipher Mode No Enumeration v1.0 + * Padding Method No Enumeration v1.0 + * Hashing Algorithm No Enumeration v1.0 + * Key Role Type No Enumeration v1.0 + * Digital Signature Algorithm No Enumeration v1.2 + * Cryptographic Algorithm No Enumeration v1.2 + * Random IV No Boolean v1.2 + * IV Length No Integer v1.2 + * Tag Length No Integer v1.2 + * Fixed Field Length No Integer v1.2 + * Invocation Field Length No Integer v1.2 + * Counter Length No Integer v1.2 + * Initial Counter Value No Integer v1.2 + * Salt Length No Integer v1.4 + * Mask Generator No Enumeration v1.4 + * Mask Generator Hashing Alg No Enumeration v1.4 + * P Source No Byte String v1.4 + * Trailer Field No Integer v1.4 + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param mode the block cipher mode (ignored if 0) + * @param padding the padding method (ignored if 0) + * @param hash_algo the hashing algorithm (ignored if 0) + * @param key_role the key role type (ignored if 0) + * @param signature_algo the signature algorithm (ignored if 0) + * @param crypto_algo the cryptographic algorithm (ignored if 0) + * @param random_iv true if a random IV is used (ignored if NULL) + * @param iv_length the IV length (ignored if NULL) + * @param tag_length the tag length (ignored if NULL) + * @param fixed_field_length the fixed field length (ignored if NULL) + * @param invoc_field_length the invocation field length (ignored if NULL) + * @param counter_length the counter length (ignored if NULL) + * @param init_counter_value the initial counter value (ignored if NULL) + * @param salt_length the salt length (ignored if NULL) + * @param mgf the mask generator (ignored if 0) + * @param mgf_hash_algo the mask generator hash algorithm (ignored if 0) + * @param trailer_field the trailer field (ignored if NULL) + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_cryptographic_parameters( + const struct kmip_version *version, + enum kmip_block_cipher_mode mode, + enum kmip_padding_method padding, + enum kmip_hashing_algo hash_algo, + enum kmip_key_role_type key_role, + enum kmip_signature_algo signature_algo, + enum kmip_crypto_algo crypto_algo, + bool *random_iv, + int32_t *iv_length, + int32_t *tag_length, + int32_t *fixed_field_length, + int32_t *invoc_field_length, + int32_t *counter_length, + int32_t *init_counter_value, + int32_t *salt_length, + enum kmip_mask_generator mgf, + enum kmip_hashing_algo mgf_hash_algo, + int32_t *trailer_field) +{ + struct kmip_node *icv = NULL, *salt = NULL, *mg = NULL, *mghash = NULL; + struct kmip_node *ret = NULL, *cmod = NULL, *pad = NULL, *hash = NULL; + struct kmip_node *krl = NULL, *sig = NULL, *algo = NULL, *riv = NULL; + struct kmip_node *iv = NULL, *tag = NULL, *ffl = NULL, *ifl = NULL; + struct kmip_node *cnt = NULL, *trl = NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + + if (mode != 0) { + cmod = kmip_node_new_enumeration(KMIP_TAG_BLOCK_CIPHER_MODE, + NULL, mode); + if (cmod == NULL) + goto out; + } + + if (padding != 0) { + pad = kmip_node_new_enumeration(KMIP_TAG_PADDING_METHOD, + NULL, padding); + if (pad == NULL) + goto out; + } + + if (hash_algo != 0) { + hash = kmip_node_new_enumeration(KMIP_TAG_HASHING_ALGORITHM, + NULL, hash_algo); + if (hash == NULL) + goto out; + } + + if (key_role != 0) { + krl = kmip_node_new_enumeration(KMIP_TAG_KEY_ROLE_TYPE, + NULL, key_role); + if (krl == NULL) + goto out; + } + + if (version->major == 1 && version->minor < 2) + goto create; + + if (signature_algo != 0) { + sig = kmip_node_new_enumeration( + KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM, + NULL, signature_algo); + if (sig == NULL) + goto out; + } + + if (crypto_algo != 0) { + algo = kmip_node_new_enumeration( + KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, + NULL, crypto_algo); + if (algo == NULL) + goto out; + } + + if (random_iv != NULL) { + riv = kmip_node_new_boolean(KMIP_TAG_RANDOM_IV, NULL, + *random_iv); + if (riv == NULL) + goto out; + } + + if (iv_length != NULL) { + iv = kmip_node_new_integer(KMIP_TAG_IV_LENGTH, NULL, + *iv_length); + if (iv == NULL) + goto out; + } + + if (tag_length != NULL) { + tag = kmip_node_new_integer(KMIP_TAG_TAG_LENGTH, NULL, + *tag_length); + if (tag == NULL) + goto out; + } + + if (fixed_field_length != NULL) { + ffl = kmip_node_new_integer(KMIP_TAG_FIXED_FIELD_LENGTH, NULL, + *fixed_field_length); + if (ffl == NULL) + goto out; + } + + if (invoc_field_length != NULL) { + ifl = kmip_node_new_integer(KMIP_TAG_INVOCATION_FIELD_LENGTH, + NULL, *invoc_field_length); + if (ifl == NULL) + goto out; + } + + + if (counter_length != NULL) { + cnt = kmip_node_new_integer(KMIP_TAG_COUNTER_LENGTH, NULL, + *counter_length); + if (cnt == NULL) + goto out; + } + + if (init_counter_value != NULL) { + icv = kmip_node_new_integer(KMIP_TAG_INITIAL_COUNTER_VALUE, + NULL, *init_counter_value); + if (icv == NULL) + goto out; + } + + if (version->major == 1 && version->minor < 4) + goto create; + + if (salt_length != NULL) { + salt = kmip_node_new_integer(KMIP_TAG_SALT_LENGTH, NULL, + *salt_length); + if (salt == NULL) + goto out; + } + + if (mgf != 0) { + mg = kmip_node_new_enumeration(KMIP_TAG_MASK_GENERATOR, + NULL, mgf); + if (mg == NULL) + goto out; + } + + if (mgf_hash_algo != 0) { + mghash = kmip_node_new_enumeration( + KMIP_TAG_MASK_GENERATOR_HASHING_ALGORITHM, + NULL, mgf_hash_algo); + if (mghash == NULL) + goto out; + } + + if (trailer_field != NULL) { + trl = kmip_node_new_integer(KMIP_TAG_TRAILER_FIELD, NULL, + *trailer_field); + if (trl == NULL) + goto out; + } + +create: + ret = kmip_node_new_structure_va(KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS, + NULL, 17, cmod, pad, hash, krl, sig, + algo, riv, iv, tag, ffl, ifl, cnt, icv, + salt, mg, mghash, trl); + +out: + kmip_node_free(cmod); + kmip_node_free(pad); + kmip_node_free(hash); + kmip_node_free(krl); + kmip_node_free(sig); + kmip_node_free(algo); + kmip_node_free(riv); + kmip_node_free(iv); + kmip_node_free(tag); + kmip_node_free(ffl); + kmip_node_free(ffl); + kmip_node_free(cnt); + kmip_node_free(icv); + kmip_node_free(salt); + kmip_node_free(mg); + kmip_node_free(mghash); + kmip_node_free(trl); + + return ret; +} + +/** + * Gets information from a Cryptographic Parameter attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Parameters Structure v1.0 + * Block Cipher Mode No Enumeration v1.0 + * Padding Method No Enumeration v1.0 + * Hashing Algorithm No Enumeration v1.0 + * Key Role Type No Enumeration v1.0 + * Digital Signature Algorithm No Enumeration v1.2 + * Cryptographic Algorithm No Enumeration v1.2 + * Random IV No Boolean v1.2 + * IV Length No Integer v1.2 + * Tag Length No Integer v1.2 + * Fixed Field Length No Integer v1.2 + * Invocation Field Length No Integer v1.2 + * Counter Length No Integer v1.2 + * Initial Counter Value No Integer v1.2 + * Salt Length No Integer v1.4 + * Mask Generator No Enumeration v1.4 + * Mask Generator Hashing Alg No Enumeration v1.4 + * P Source No Byte String v1.4 + * Trailer Field No Integer v1.4 + * + * @param node the KMIP node + * @param mode On return: the block cipher mode (0 if not avail, + * can be NULL) + * @param padding On return: the padding method (0 if not avail, + * can be NULL) + * @param hash_algo On return: the hashing algorithm (0 if not avail, + * can be NULL) + * @param key_role On return: the key role type (0 if not avail, + * can be NULL) + * @param signature_algo On return: the signature algorithm (0 if not avail, + * can be NULL) + * @param crypto_algo On return: the cryptographic algorithm (0 if not + * avail, can be NULL) + * @param random_iv On return: true if a random IV is used (false if + * not avail, can be NULL) + * @param iv_length On return: the IV length (-1 if not avail, can be + * NULL) + * @param tag_length On return: the tag length (-1 if not avail, can be + * NULL) + * @param fixed_field_length On return: the fixed field length (-1 if not avail, + * can be NULL) + * @param invoc_field_length On return: the invocation field length (-1 if not + * avail, can be NULL) + * @param counter_length On return: the counter length (-1 if not avail, + * can be NULL) + * @param init_counter_value On return: the initial counter value (0 if not + * avail, can be NULL) + * @param salt_length On return: the salt length (-1 if not avail, + * can be NULL) + * @param mgf On return: the mask generator (0 if not avail, + * can be NULL) + * @param mgf_hash_algo On return: the mask generator hash algorithm (0 if + * not avail, can be NULL) + * @param trailer_field On return: the trailer field (0 if not avail, + * can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_cryptographic_parameter(const struct kmip_node *node, + enum kmip_block_cipher_mode *mode, + enum kmip_padding_method *padding, + enum kmip_hashing_algo *hash_algo, + enum kmip_key_role_type *key_role, + enum kmip_signature_algo *signature_algo, + enum kmip_crypto_algo *crypto_algo, + bool *random_iv, + int32_t *iv_length, + int32_t *tag_length, + int32_t *fixed_field_length, + int32_t *invoc_field_length, + int32_t *counter_length, + int32_t *init_counter_value, + int32_t *salt_length, + enum kmip_mask_generator *mgf, + enum kmip_hashing_algo *mgf_hash_algo, + int32_t *trailer_field) +{ + struct kmip_node *n; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS) + return -EBADMSG; + + if (mode != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_BLOCK_CIPHER_MODE, 0); + *mode = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (padding != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_PADDING_METHOD, 0); + *padding = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (hash_algo != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_HASHING_ALGORITHM, 0); + *hash_algo = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (key_role != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_ROLE_TYPE, 0); + *key_role = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (signature_algo != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM, 0); + *signature_algo = + (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (crypto_algo != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, 0); + *crypto_algo = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (random_iv != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_RANDOM_IV, 0); + *random_iv = (n != NULL ? kmip_node_get_boolean(n) : false); + kmip_node_free(n); + } + + if (iv_length != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_IV_LENGTH, 0); + *iv_length = (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (tag_length != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_TAG_LENGTH, 0); + *tag_length = (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (fixed_field_length != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_FIXED_FIELD_LENGTH, 0); + *fixed_field_length = + (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (invoc_field_length != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_INVOCATION_FIELD_LENGTH, 0); + *invoc_field_length = + (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (counter_length != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_COUNTER_LENGTH, 0); + *counter_length = (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (init_counter_value != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_INITIAL_COUNTER_VALUE, 0); + *init_counter_value = + (n != NULL ? kmip_node_get_integer(n) : 0); + kmip_node_free(n); + } + + if (salt_length != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_SALT_LENGTH, 0); + *salt_length = (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (mgf != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_MASK_GENERATOR, 0); + *mgf = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (mgf_hash_algo != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_MASK_GENERATOR_HASHING_ALGORITHM, 0); + *mgf_hash_algo = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (trailer_field != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_TRAILER_FIELD, 0); + *trailer_field = (n != NULL ? kmip_node_get_integer(n) : 0); + kmip_node_free(n); + } + + return 0; +} + +/** + * Constructs a Cryptographic Domain Parameters attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Domain Params Yes Structure v1.0 + * Qlength No Integer v1.0 + * Recommended Curve No Enumeration v1.0 + * + * @param qlength the Q length (ignored of <= 0) + * @param curve the curve (ignored if 0) + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_cryptographic_domain_parameters( + int32_t qlength, + enum kmip_recommended_curve curve) +{ + struct kmip_node *ret = NULL, *qlen = NULL, *crv = NULL; + + if (qlength > 0) { + qlen = kmip_node_new_integer(KMIP_TAG_Q_LENGTH, NULL, qlength); + if (qlen == NULL) + goto out; + } + + if (curve != 0) { + crv = kmip_node_new_enumeration(KMIP_TAG_RECOMMENDED_CURVE, + NULL, curve); + if (crv == NULL) + goto out; + } + + ret = kmip_node_new_structure_va( + KMIP_TAG_CRYPTOGRAPHIC_DOMAIN_PARAMETERS, NULL, 2, + qlen, crv); + +out: + kmip_node_free(qlen); + kmip_node_free(crv); + + return ret; +} + +/** + * Gets the information from a Cryptographic Domain Parameters attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Cryptographic Domain Params Yes Structure v1.0 + * Qlength No Integer v1.0 + * Recommended Curve No Enumeration v1.0 + * + * @param node the KMIP node + * @param qlength On return: the Q length (-1 if not avail, can be + * NULL) + * @param curve On return: the curve (0 if not avail, can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_cryptographic_domain_parameters(const struct kmip_node *node, + int32_t *qlength, + enum kmip_recommended_curve *curve) +{ + struct kmip_node *n; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_CRYPTOGRAPHIC_DOMAIN_PARAMETERS) + return -EBADMSG; + + if (qlength != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_Q_LENGTH, 0); + *qlength = (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (curve != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_RECOMMENDED_CURVE, 0); + *curve = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + return 0; +} + +/** + * Constructs a Digital Signature Algorithm attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Digital Signature Algorithm Yes Enumeration v1.2 + * + * @param signature_algo the signature algorithm + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_digital_signature_algorithm( + enum kmip_signature_algo signature_algo) +{ + return kmip_node_new_enumeration(KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM, + NULL, signature_algo); +} + +/** + * Gets the information from a Digital Signature Algorithm attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Digital Signature Algorithm Yes Enumeration v1.2 + * + * @param node the KMIP node + * @param signature_algo the signature algorithm + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_digital_signature_algorithm(const struct kmip_node *node, + enum kmip_signature_algo *signature_algo) +{ + if (node == NULL || signature_algo == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM) + return -EBADMSG; + + *signature_algo = kmip_node_get_enumeration(node); + return 0; +} + +/** + * Constructs a Object Group attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Object Group Yes Text String v1.0 + * + * @param group the object group + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_object_group(const char *group) +{ + return kmip_node_new_text_string(KMIP_TAG_OBJECT_GROUP, NULL, group); +} + +/** + * Gets the information from a Object Group attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Object Group Yes Text String v1.0 + * + * @param node the KMIP node + * @param group the object group + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_object_group(const struct kmip_node *node, const char **group) +{ + if (node == NULL || group == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_OBJECT_GROUP) + return -EBADMSG; + + *group = kmip_node_get_text_string(node); + return 0; +} + +/** + * Constructs a Revocation Reason attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Revocation Reason Yes Structure v1.0 + * Revocation Reason Code Yes Enumeration v1.0 + * Revocation Message No Text String v1.0 + * + * @param reason the revocation reason code + * @param message the revocation message (can be NULL) + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_revocation_reason(enum kmip_revoke_reason reason, + const char *message) +{ + struct kmip_node *ret = NULL, *rsn, *msg = NULL; + + rsn = kmip_node_new_enumeration(KMIP_TAG_REVOCATION_REASON_CODE, NULL, + reason); + if (rsn == NULL) + goto out; + if (message != NULL) { + msg = kmip_node_new_text_string(KMIP_TAG_REVOCATION_MESSAGE, + NULL, message); + if (msg == NULL) + goto out; + } + + ret = kmip_node_new_structure_va(KMIP_TAG_REVOCATION_REASON, NULL, 2, + rsn, msg); + +out: + kmip_node_free(rsn); + kmip_node_free(msg); + + return ret; +} + +/** + * Gets the information from a Revocation Reason attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Revocation Reason Yes Structure v1.0 + * Revocation Reason Code Yes Enumeration v1.0 + * Revocation Message No Text String v1.0 + * + * @param node the KMIP node + * @param reason the revocation reason code + * @param message the revocation message (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_revocation_reason(const struct kmip_node *node, + enum kmip_revoke_reason *reason, + const char **message) +{ + struct kmip_node *n; + + if (node == NULL || reason == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_REVOCATION_REASON) + return -EBADMSG; + + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_REVOCATION_REASON_CODE, 0); + if (n == NULL) + return -EBADMSG; + *reason = kmip_node_get_enumeration(n); + kmip_node_free(n); + + if (message != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_REVOCATION_MESSAGE, 0); + *message = (n != NULL ? kmip_node_get_text_string(n) : NULL); + kmip_node_free(n); + } + + return 0; +} + +/** + * Constructs a Contact Information attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Contact Information Yes Text String v1.0 + * + * @param contact the contact information + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_contact_information(const char *contact) +{ + return kmip_node_new_text_string(KMIP_TAG_CONTACT_INFORMATION, NULL, + contact); +} + +/** + * Gets the information from a Contact Information attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Contact Information Yes Text String v1.0 + * + * @param node the KMIP node + * @param contact the contact information + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_contact_information(const struct kmip_node *node, + const char **contact) +{ + if (node == NULL || contact == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_CONTACT_INFORMATION) + return -EBADMSG; + + *contact = kmip_node_get_text_string(node); + return 0; +} + +/** + * Constructs a Description attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Description Yes Text String v1.4 + * + * @param description the description + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_description(const char *description) +{ + return kmip_node_new_text_string(KMIP_TAG_DESCRIPTION, NULL, + description); +} + +/** + * Gets the information from a Description attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Description Yes Text String v1.4 + * + * @param node the KMIP node + * @param description the description + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_description(const struct kmip_node *node, const char **description) +{ + if (node == NULL || description == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_DESCRIPTION) + return -EBADMSG; + + *description = kmip_node_get_text_string(node); + return 0; +} + +/** + * Constructs a Comment attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Comment Yes Text String v1.4 + * + * @param comment the comment + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_comment(const char *comment) +{ + return kmip_node_new_text_string(KMIP_TAG_COMMENT, NULL, comment); +} + +/** + * Gets the information from a Comment attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Comment Yes Text String v1.4 + * + * @param node the KMIP node + * @param comment the comment + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_comment(const struct kmip_node *node, const char **comment) +{ + if (node == NULL || comment == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_COMMENT) + return -EBADMSG; + + *comment = kmip_node_get_text_string(node); + return 0; +} + +/** + * Constructs a Key Format Type attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Format Type Yes Enumeration v2.0 + * + * @param type the key format type + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_key_format_type(enum kmip_key_format_type type) +{ + return kmip_node_new_enumeration(KMIP_TAG_KEY_FORMAT_TYPE, NULL, type); +} + +/** + * Gets the information from a Key Format Type attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Format Type Yes Enumeration v2.0 + * + * @param node the KMIP node + * @param type the key format type + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_key_format_type(const struct kmip_node *node, + enum kmip_key_format_type *type) +{ + if (node == NULL || type == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_FORMAT_TYPE) + return -EBADMSG; + + *type = kmip_node_get_enumeration(node); + return 0; +} + +/** + * Constructs a Protection Level attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Level Yes Enumeration v2.0 + * + * @param level the protection level + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_protection_level(enum kmip_protection_level level) +{ + return kmip_node_new_enumeration(KMIP_TAG_PROTECTION_LEVEL, NULL, + level); +} + +/** + * Gets the information from a Protection Level attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Level Yes Enumeration v2.0 + * + * @param node the KMIP node + * @param level the protection level + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_protection_level(const struct kmip_node *node, + enum kmip_protection_level *level) +{ + if (node == NULL || level == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_PROTECTION_LEVEL) + return -EBADMSG; + + *level = kmip_node_get_enumeration(node); + return 0; +} + +/** + * Constructs a Protection Period attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Period Yes Interval v2.0 + * + * @param period the protection period + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_protection_period(uint32_t period) +{ + return kmip_node_new_interval(KMIP_TAG_PROTECTION_PERIOD, NULL, period); +} + +/** + * Gets the information from a Protection Period attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Period Yes Interval v2.0 + * + * @param node the KMIP node + * @param period the protection period + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_protection_period(const struct kmip_node *node, uint32_t *period) +{ + if (node == NULL || period == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_PROTECTION_PERIOD) + return -EBADMSG; + + *period = kmip_node_get_interval(node); + return 0; +} + +/** + * Constructs a Protection Storage Mask attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Storage Mask Yes Integer v2.0 + * + * @param protection_mask the protection mask + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_protection_storage_mask(int32_t protection_mask) +{ + return kmip_node_new_integer(KMIP_TAG_PROTECTION_STORAGE_MASK, NULL, + protection_mask); +} + +/** + * Gets the information from a Protection Storage Mask attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Storage Mask Yes Integer v2.0 + * + * @param node the KMIP node + * @param protection_mask the protection mask + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_protection_storage_mask(const struct kmip_node *node, + int32_t *protection_mask) +{ + if (node == NULL || protection_mask == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_PROTECTION_STORAGE_MASK) + return -EBADMSG; + + *protection_mask = kmip_node_get_integer(node); + return 0; +} + +/** + * Constructs a Fresh attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Fresh Yes Boolean v1.2 + * + * @param fresh the fresh value + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_fresh(bool fresh) +{ + return kmip_node_new_boolean(KMIP_TAG_FRESH, NULL, fresh); +} + +/** + * Gets the information from a Fresh attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Fresh Yes Boolean v1.2 + * + * @param node the KMIP node + * @param fresh the fresh value + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_fresh(const struct kmip_node *node, bool *fresh) +{ + if (node == NULL || fresh == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_FRESH) + return -EBADMSG; + + *fresh = kmip_node_get_boolean(node); + return 0; +} + +/** + * Constructs a Key Value Present attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Value Present Yes Boolean v1.2 + * + * @param present the present value + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_key_value_present(bool present) +{ + return kmip_node_new_boolean(KMIP_TAG_KEY_VALUE_PRESENT, NULL, present); +} + +/** + * Gets the information from a Key Value Present attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Value Present Yes Boolean v1.2 + * + * @param node the KMIP node + * @param present the present value + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_key_value_present(const struct kmip_node *node, bool *present) +{ + if (node == NULL || present == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_VALUE_PRESENT) + return -EBADMSG; + + *present = kmip_node_get_boolean(node); + return 0; +} + +/** + * Constructs a Short Unique Identifier attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Short Unique Identifier Yes Byte String v2.0 + * + * @param short_uid the short unique identifier + * @param short_uid_len the length of the short unique identifier + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_short_unique_identifier( + const unsigned char *short_uid, + uint32_t short_uid_len) +{ + return kmip_node_new_byte_string(KMIP_TAG_SHORT_UNIQUE_IDENTIFIER, NULL, + short_uid, short_uid_len); +} + +/** + * Gets the information from a Short Unique Identifier attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Short Unique Identifier Yes Byte String v2.0 + * + * @param node the KMIP node + * @param short_uid the short unique identifier + * @param short_uid_len the length of the short unique identifier + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_short_unique_identifier(const struct kmip_node *node, + const unsigned char **short_uid, + uint32_t *short_uid_len) +{ + if (node == NULL || short_uid == NULL || short_uid_len == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_SHORT_UNIQUE_IDENTIFIER) + return -EBADMSG; + + *short_uid = kmip_node_get_byte_string(node, short_uid_len); + return 0; +} + +/** + * Constructs a Application Specific Information attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Application Specific Info. Yes Structure v1.0 + * Application Namespace Yes Text String v1.0 + * Application Data Yes/No Text String v1.0 + * + * @param name_space the application namespace + * @param data the application data + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_application_specific_information( + const char *name_space, const char *data) +{ + struct kmip_node *ret = NULL, *ns, *d = NULL; + + if (name_space == NULL) + return NULL; + + ns = kmip_node_new_text_string(KMIP_TAG_APPLICATION_NAMESPACE, NULL, + name_space); + if (ns == NULL) + goto out; + if (data != NULL) { + d = kmip_node_new_text_string(KMIP_TAG_APPLICATION_DATA, NULL, + data); + if (d == NULL) + goto out; + } + + ret = kmip_node_new_structure_va(KMIP_TAG_APPLICATION_DATA, NULL, 2, + ns, d); + +out: + kmip_node_free(ns); + kmip_node_free(d); + + return ret; +} + +/** + * Gets the information from a Application Specific Information attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Application Specific Info. Yes Structure v1.0 + * Application Namespace Yes Text String v1.0 + * Application Data Yes/No Text String v1.0 + * + * @param node the KMIP node + * @param name_space the application namespace + * @param data the application data (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_application_specific_information(const struct kmip_node *node, + const char **name_space, + const char **data) +{ + struct kmip_node *n; + + if (node == NULL || name_space == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_APPLICATION_DATA) + return -EBADMSG; + + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_APPLICATION_NAMESPACE, 0); + if (n == NULL) + return -EBADMSG; + *name_space = kmip_node_get_text_string(n); + kmip_node_free(n); + + if (data != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_APPLICATION_DATA, 0); + if (n == NULL) + return -EBADMSG; + *data = kmip_node_get_text_string(n); + kmip_node_free(n); + } + + return 0; +} + +/** + * Constructs a Key Value Location attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Value Location Yes Structure v1.2 + * Key Value Location Value Yes Text String v1.2 + * Key Value Location Type Yes Enumeration v1.2 + * + * @param value the value of the key value location + * @param type the type of the key value location + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_key_value_location(const char *value, + enum kmip_key_value_location_type type) +{ + struct kmip_node *name = NULL, *val, *typ; + + if (value == NULL) + return NULL; + + val = kmip_node_new_text_string(KMIP_TAG_KEY_VALUE_LOCATION_VALUE, NULL, + value); + typ = kmip_node_new_enumeration(KMIP_TAG_KEY_VALUE_LOCATION_TYPE, NULL, + type); + if (val == NULL || typ == NULL) + goto out; + + name = kmip_node_new_structure_va(KMIP_TAG_KEY_VALUE_LOCATION, NULL, 2, + val, typ); + +out: + kmip_node_free(val); + kmip_node_free(typ); + + return name; +} + +/** + * Gets the information from a Key Value Location attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Value Location Yes Structure v1.2 + * Key Value Location Value Yes Text String v1.2 + * Key Value Location Type Yes Enumeration v1.2 + * + * @param node the KMIP node + * @param value the value of the key value location + * @param type the type of the key value location + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_key_value_location(const struct kmip_node *node, + const char **value, enum kmip_key_value_location_type *type) +{ + struct kmip_node *val, *typ; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_VALUE_LOCATION) + return -EBADMSG; + + val = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_VALUE_LOCATION_VALUE, 0); + typ = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_VALUE_LOCATION_TYPE, 0); + if (val == NULL || typ == NULL) { + rc = -EBADMSG; + goto out; + } + + if (value != NULL) + *value = kmip_node_get_text_string(val); + if (type != NULL) + *type = kmip_node_get_enumeration(typ); + +out: + kmip_node_free(val); + kmip_node_free(typ); + + return rc; +} + +/** + * Constructs a Digest attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Digest Yes Structure v1.0 + * Hashing Algorithm Yes Enumeration v1.0 + * Digest Value Yes Byte String v1.0 + * + * @param hash_algo the hashing algorithm + * @param digest the digest value + * @param digest_len the digest length + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_digest(enum kmip_hashing_algo hash_algo, + const unsigned char *digest, + uint32_t digest_len) +{ + struct kmip_node *ret = NULL, *algo, *val; + + if (digest == NULL || digest_len == 0) + return NULL; + + algo = kmip_node_new_enumeration(KMIP_TAG_HASHING_ALGORITHM, NULL, + hash_algo); + val = kmip_node_new_byte_string(KMIP_TAG_DIGEST_VALUE, NULL, + digest, digest_len); + if (algo == NULL || val == NULL) + goto out; + + ret = kmip_node_new_structure_va(KMIP_TAG_DIGEST, NULL, 2, algo, val); + +out: + kmip_node_free(algo); + kmip_node_free(val); + + return ret; +} + +/** + * Gets the information from a Digest attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Digest Yes Structure v1.0 + * Hashing Algorithm Yes Enumeration v1.0 + * Digest Value Yes Byte String v1.0 + * + * @param node the KMIP node + * @param hash_algo the hashing algorithm (can be NULL) + * @param digest the digest value (can be NULL) + * @param digest_len the digest length (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_digest(const struct kmip_node *node, + enum kmip_hashing_algo *hash_algo, + const unsigned char **digest, uint32_t *digest_len) +{ + struct kmip_node *algo, *val; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_DIGEST) + return -EBADMSG; + + algo = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_HASHING_ALGORITHM, 0); + val = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_DIGEST_VALUE, 0); + if (algo == NULL || val == NULL) { + rc = -EBADMSG; + goto out; + } + + if (hash_algo != NULL) + *hash_algo = kmip_node_get_enumeration(algo); + if (digest != NULL) + *digest = kmip_node_get_byte_string(val, digest_len); + +out: + kmip_node_free(algo); + kmip_node_free(val); + + return rc; +} + +/** + * Constructs a Sensitive attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Sensitive Yes Boolean v1.4 + * + * @param sensitive the sensitive value + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_sensitive(bool sensitive) +{ + return kmip_node_new_boolean(KMIP_TAG_SENSITIVE, NULL, sensitive); +} + +/** + * Gets the information from a Sensitive attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Sensitive Yes Boolean v1.4 + * + * @param node the KMIP node + * @param sensitive the sensitive value + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_sensitive(const struct kmip_node *node, bool *sensitive) +{ + if (node == NULL || sensitive == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_SENSITIVE) + return -EBADMSG; + + *sensitive = kmip_node_get_boolean(node); + return 0; +} + +/** + * Constructs a Always Sensitive attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Always Sensitive Yes Boolean v1.4 + * + * @param sensitive the sensitive value + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_always_sensitive(bool sensitive) +{ + return kmip_node_new_boolean(KMIP_TAG_ALWAYS_SENSITIVE, NULL, + sensitive); +} + +/** + * Gets the information from a Always Sensitive attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Always Sensitive Yes Boolean v1.4 + * + * @param node the KMIP node + * @param sensitive the sensitive value + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_always_sensitive(const struct kmip_node *node, bool *sensitive) +{ + if (node == NULL || sensitive == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_ALWAYS_SENSITIVE) + return -EBADMSG; + + *sensitive = kmip_node_get_boolean(node); + return 0; +} + +/** + * Constructs a Extractable attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Extractable Yes Boolean v1.4 + * + * @param extractable the extractable value + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_extractable(bool extractable) +{ + return kmip_node_new_boolean(KMIP_TAG_EXTRACTABLE, NULL, extractable); +} + +/** + * Gets the information from a Extractable attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Extractable Yes Boolean v1.4 + * + * @param node the KMIP node + * @param extractable the extractable value + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_extractable(const struct kmip_node *node, bool *extractable) +{ + if (node == NULL || extractable == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_EXTRACTABLE) + return -EBADMSG; + + *extractable = kmip_node_get_boolean(node); + return 0; +} + +/** + * Constructs a Never Extractable attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Never Extractable Yes Boolean v1.4 + * + * @param extractable the extractable value + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_never_extractable(bool extractable) +{ + return kmip_node_new_boolean(KMIP_TAG_NEVER_EXTRACTABLE, NULL, + extractable); +} + +/** + * Gets the information from a Never Extractable attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Never Extractable Yes Boolean v1.4 + * + * @param node the KMIP node + * @param extractable the extractable value + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_never_extractable(const struct kmip_node *node, bool *extractable) +{ + if (node == NULL || extractable == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_NEVER_EXTRACTABLE) + return -EBADMSG; + + *extractable = kmip_node_get_boolean(node); + return 0; +} + +/** + * Constructs a Link attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Link Yes Structure v1.0 + * Link Type Yes Enumeration v1.0 + * Linked Object Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param type the link type + * @param obj_id the linked object identifier + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_link(enum kmip_link_type type, + struct kmip_node *obj_id) +{ + struct kmip_node *ret = NULL, *typ; + + if (obj_id == NULL) + return NULL; + + typ = kmip_node_new_enumeration(KMIP_TAG_LINK_TYPE, NULL, + type); + if (typ == NULL) + return NULL; + + ret = kmip_node_new_structure_va(KMIP_TAG_LINK, NULL, 2, + typ, obj_id); + kmip_node_free(typ); + + return ret; +} + +/** + * Gets the information from a Link attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Link Yes Structure v1.0 + * Link Type Yes Enumeration v1.0 + * Linked Object Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + + * + * @param node the KMIP node + * @param type the link type + * @param obj_id the linked object identifier + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_link(const struct kmip_node *node, enum kmip_link_type *type, + struct kmip_node **obj_id) +{ + struct kmip_node *n; + + if (type == NULL || obj_id == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_LINK) + return -EBADMSG; + + n = kmip_node_get_structure_element_by_tag(node, KMIP_TAG_LINK_TYPE, 0); + if (n == NULL) + return -EBADMSG; + *type = kmip_node_get_enumeration(n); + kmip_node_free(n); + + *obj_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_LINKED_OBJECT_IDENTIFIER, 0); + if (*obj_id == NULL) + return -EBADMSG; + + return 0; +} + +/** + * Constructs a Linked Object Identifier attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Linked Object Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param text_id the linked identifier as text string (or NULL) + * @param enum_id the linked identifier as enumeration (or 0) + * @param int_id the linked identifier as integer + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_linked_object_identifier(const char *text_id, + enum kmip_unique_identifier enum_id, + int32_t int_id) +{ + if (text_id != NULL && enum_id != 0) + return NULL; + + if (text_id != NULL) + return kmip_node_new_text_string( + KMIP_TAG_LINKED_OBJECT_IDENTIFIER, NULL, text_id); + if (enum_id != 0) + return kmip_node_new_enumeration( + KMIP_TAG_LINKED_OBJECT_IDENTIFIER, NULL, enum_id); + + return kmip_node_new_integer(KMIP_TAG_LINKED_OBJECT_IDENTIFIER, NULL, + int_id); +} + +/** + * Gets the information from a Linked Object Identifier attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Linked Object Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param text_id the linked identifier as text string (can be NULL) + * @param enum_id the linked identifier as enumeration (can be NULL) + * @param int_id the linked identifier as integer (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_linked_object_identifier(const struct kmip_node *node, + const char **text_id, + enum kmip_unique_identifier *enum_id, + int32_t *int_id) +{ + if (node == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_LINKED_OBJECT_IDENTIFIER) + return -EBADMSG; + + if (text_id != NULL) { + if (kmip_node_get_type(node) == KMIP_TYPE_TEXT_STRING) + *text_id = kmip_node_get_text_string(node); + else + *text_id = NULL; + } + + if (enum_id != NULL) { + if (kmip_node_get_type(node) == KMIP_TYPE_ENUMERATION) + *enum_id = kmip_node_get_enumeration(node); + else + *enum_id = 0; + } + + if (int_id != NULL) { + if (kmip_node_get_type(node) == KMIP_TYPE_INTEGER) + *int_id = kmip_node_get_integer(node); + else + *int_id = 0; + } + + return 0; +} + +/** + * Constructs a Operation Policy Name attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Operation Policy Name Yes Text String v1.x only + * + * @param policy the policy name + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_operation_policy_name(const char *policy) +{ + return kmip_node_new_text_string(KMIP_TAG_OPERATION_POLICY_NAME, NULL, + policy); +} + +/** + * Gets the information from a Operation Policy Name attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Operation Policy Name Yes Text String v1.x only + * + * @param node the KMIP node + * @param policy the policy name + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_operation_policy_name(const struct kmip_node *node, + const char **policy) +{ + if (node == NULL || policy == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_OPERATION_POLICY_NAME) + return -EBADMSG; + + *policy = kmip_node_get_text_string(node); + return 0; +} + +/** + * Constructs a Lease Time attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Lease Time Yes Interval v1.0 + * + * @param lease_time the lease time + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_lease_time(uint32_t lease_time) +{ + return kmip_node_new_interval(KMIP_TAG_LEASE_TIME, NULL, lease_time); +} + +/** + * Gets the information from a Lease Time attribute node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Lease Time Yes Interval v1.0 + * + * @param node the KMIP node + * @param lease_time the lease time + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_lease_time(const struct kmip_node *node, uint32_t *lease_time) +{ + if (node == NULL || lease_time == NULL) + return -EBADMSG; + + if (kmip_node_get_tag(node) != KMIP_TAG_LEASE_TIME) + return -EBADMSG; + + *lease_time = kmip_node_get_interval(node); + return 0; +} + diff --git a/libkmipclient/https.c b/libkmipclient/https.c new file mode 100644 index 00000000..2cea1276 --- /dev/null +++ b/libkmipclient/https.c @@ -0,0 +1,848 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include +#include + +#include +#include +#include + +#include "lib/zt_common.h" + +#include "kmip.h" +#include "utils.h" + +#define HTTP_HDR_CONTENT_TYPE "Content-Type:" + +#define CURL_ERROR_CHECK(rc, text, debug, label) \ + do { \ + if ((rc) != CURLE_OK) { \ + kmip_debug((debug), "%s: %s", (text), \ + curl_easy_strerror((rc))); \ + goto label; \ + } \ + } while (0) + +struct curl_sslctx_cb_data { + const struct kmip_connection *conn; + bool debug; +}; + +struct curl_write_cb_data { + const struct kmip_connection *conn; + bool error; + bool debug; + union { + struct { + json_tokener *tok; + json_object *resp_obj; + } json; + struct { + xmlParserCtxtPtr ctx; + } xml; + struct { + BIO *resp_mem_bio; + } ttlv; + }; +}; + +struct curl_header_cb_data { + const struct kmip_connection *conn; + bool error; + bool debug; +}; + +/** + * Initializes a new HTTPS connection to a KMIP server. + * + * @param connn The KMIP connection + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_connection_https_init(struct kmip_connection *conn, bool debug) +{ + const char *content_type, *accept, *server, *tok; + const struct curl_tlssessioninfo *info = NULL; + bool port_found = false; + struct stat sb; + int rc; + + if (conn == NULL) + return -EINVAL; + + if (strncmp(conn->config.server, "https://", 8) != 0) { + kmip_debug(debug, "Server must start with 'https://'"); + return -EINVAL; + } + + /* Find port (if any) and beginning of uri */ + server = conn->config.server + 8; + if (*server == '[') { + /* IPv6 address enclosed in square brackets */ + tok = strchr(server, ']'); + if (tok == NULL) { + kmip_debug(debug, "malformed IPv6 address"); + return -EINVAL; + } + tok++; + port_found = (*tok == ':'); + } else { + /* hostname or IPv4 address */ + tok = strchr(server, ':'); + port_found = (tok != NULL); + } + + conn->https.curl = curl_easy_init(); + if (conn->https.curl == NULL) { + kmip_debug(debug, "curl_easy_init failed"); + return -EIO; + } + + /* + * The CURLOPT_SSL_CTX_FUNCTION callback only works with the OpenSSL + * curl backend. Check that OpenSSL is the current curl backend. + */ + rc = curl_easy_getinfo(conn->https.curl, CURLINFO_TLS_SSL_PTR, &info); + CURL_ERROR_CHECK(rc, "curl_easy_getinfo CURLINFO_TLS_SSL_PTR", debug, + out); + if (info->backend != CURLSSLBACKEND_OPENSSL) { + kmip_debug(debug, "libcurl is not using the OpenSSL backend"); + rc = -EIO; + goto out; + } + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_VERBOSE, debug ? 1 : 0); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_VERBOSE", debug, out); + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_URL, + conn->config.server); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_URL", debug, out); + + if (!port_found) { + rc = curl_easy_setopt(conn->https.curl, CURLOPT_PORT, + KMIP_DEFAULT_HTTPS_PORT_NUM); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_URL", debug, + out); + } + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_SSL_VERIFYPEER, + conn->config.tls_verify_peer ? 1L : 0L); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_SSL_VERIFYPEER", debug, + out); + rc = curl_easy_setopt(conn->https.curl, CURLOPT_SSL_VERIFYHOST, + conn->config.tls_verify_host ? 2L : 0L); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_SSL_VERIFYHOST", debug, + out); + + if (conn->config.tls_ca != NULL) { + if (stat(conn->config.tls_ca, &sb) != 0) { + rc = -errno; + kmip_debug(debug, "stat failed on '%s': %s", + conn->config.tls_ca, strerror(-rc)); + goto out; + } + + if (S_ISDIR(sb.st_mode)) { + rc = curl_easy_setopt(conn->https.curl, CURLOPT_CAPATH, + conn->config.tls_ca); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_CAPATH", + debug, out); + } else { + rc = curl_easy_setopt(conn->https.curl, CURLOPT_CAINFO, + conn->config.tls_ca); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_CAINFO", + debug, out); + } + } + + if (conn->config.tls_issuer_cert != NULL) { + rc = curl_easy_setopt(conn->https.curl, CURLOPT_ISSUERCERT, + conn->config.tls_issuer_cert); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_ISSUERCERT", + debug, out); + } + + if (conn->config.tls_pinned_pubkey != NULL) { + rc = curl_easy_setopt(conn->https.curl, CURLOPT_PINNEDPUBLICKEY, + conn->config.tls_pinned_pubkey); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_PINNEDPUBLICKEY", + debug, out); + } + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_FOLLOWLOCATION, 0L); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_FOLLOWLOCATION", + debug, out); + + if (conn->config.tls_cipher_list != NULL) { + rc = curl_easy_setopt(conn->https.curl, CURLOPT_SSL_CIPHER_LIST, + conn->config.tls_cipher_list); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_SSL_CIPHER_LIST", + debug, out); + } + + if (conn->config.tls13_cipher_list != NULL) { + rc = curl_easy_setopt(conn->https.curl, CURLOPT_TLS13_CIPHERS, + conn->config.tls13_cipher_list); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_TLS13_CIPHERS", + debug, out); + } + + switch (conn->config.encoding) { + case KMIP_ENCODING_TTLV: + content_type = "Content-Type: application/octet-stream"; + accept = "Accept: application/octet-stream"; + break; + case KMIP_ENCODING_JSON: + content_type = "Content-Type: application/json;charset=UTF-8"; + accept = "Accept: application/json"; + break; + case KMIP_ENCODING_XML: + content_type = "Content-Type: text/xml;charset=UTF-8"; + accept = "Accept: text/xml"; + break; + default: + kmip_debug(debug, "invalid encoding: %d", + conn->config.encoding); + rc = -EINVAL; + goto out; + } + + conn->https.headers = curl_slist_append(conn->https.headers, + content_type); + if (conn->https.headers == NULL) { + kmip_debug(debug, "curl_slist_append failed"); + rc = -ENOMEM; + goto out; + } + + conn->https.headers = curl_slist_append(conn->https.headers, accept); + if (conn->https.headers == NULL) { + kmip_debug(debug, "curl_slist_append failed"); + rc = -ENOMEM; + goto out; + } + + conn->https.headers = curl_slist_append(conn->https.headers, + "Accept-Charset: UTF-8"); + if (conn->https.headers == NULL) { + kmip_debug(debug, "curl_slist_append failed"); + rc = -ENOMEM; + goto out; + } + + /* Disable "Expect: 100-continue" */ + conn->https.headers = curl_slist_append(conn->https.headers, "Expect:"); + if (conn->https.headers == NULL) { + kmip_debug(debug, "curl_slist_append failed"); + rc = -ENOMEM; + goto out; + } + + /* As per KMIP HTTPS profile: Cache-Control: no-cache */ + conn->https.headers = curl_slist_append(conn->https.headers, + "Cache-Control: no-cache"); + if (conn->https.headers == NULL) { + kmip_debug(debug, "curl_slist_append failed"); + rc = -ENOMEM; + goto out; + } + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_HTTPHEADER, + conn->https.headers); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_HTTPHEADER", debug, + out); + + rc = 0; + +out: + if (rc != 0) + kmip_connection_https_term(conn); + + return rc; +} + +/** + * This callback called before the SSL handshake is performed. + * It sets the client certificate and private key into the context. + * It also adds a pinned server certificate to the SSL certificate store, so + * that it is treated as trusted, although it might be self-signed. + */ +static CURLcode mkip_connection_https_sslctx_cb(CURL *UNUSED(curl), + void *sslctx, void *parm) +{ + struct curl_sslctx_cb_data *sslctx_cb = parm; + SSL_CTX *ssl_ctx = (SSL_CTX *)sslctx; + const struct kmip_connection *conn; + X509_STORE *store; + X509 *cert = NULL; + FILE *fp; + int rc; + + if (ssl_ctx == NULL || sslctx_cb == NULL || sslctx_cb->conn == NULL) + return CURLE_ABORTED_BY_CALLBACK; + + conn = sslctx_cb->conn; + + if (SSL_CTX_use_certificate_file(sslctx, conn->config.tls_client_cert, + SSL_FILETYPE_PEM) != 1) { + kmip_debug(sslctx_cb->debug, "Failed to load the client " + "certificate '%s'", conn->config.tls_client_cert); + if (sslctx_cb->debug) + ERR_print_errors_fp(stderr); + return CURLE_ABORTED_BY_CALLBACK; + } + + if (SSL_CTX_use_PrivateKey(ssl_ctx, conn->config.tls_client_key) != 1) { + kmip_debug(sslctx_cb->debug, "Failed to set the client key"); + if (sslctx_cb->debug) + ERR_print_errors_fp(stderr); + return CURLE_ABORTED_BY_CALLBACK; + } + + if (conn->config.tls_server_cert == NULL) + return CURLE_OK; + + store = SSL_CTX_get_cert_store(ssl_ctx); + if (store == NULL) { + kmip_debug(sslctx_cb->debug, "Failed to get SSL Store"); + if (sslctx_cb->debug) + ERR_print_errors_fp(stderr); + return CURLE_ABORTED_BY_CALLBACK; + } + + fp = fopen(conn->config.tls_server_cert, "r"); + if (fp == NULL) { + rc = -errno; + kmip_debug(sslctx_cb->debug, + "Failed to read server cert '%s': %s", + conn->config.tls_server_cert, strerror(-rc)); + return CURLE_ABORTED_BY_CALLBACK; + } + + cert = PEM_read_X509(fp, NULL, NULL, NULL); + fclose(fp); + + if (cert == NULL) { + kmip_debug(sslctx_cb->debug, "Failed to read the server " + "certificate from file '%s'", + conn->config.tls_server_cert); + if (sslctx_cb->debug) + ERR_print_errors_fp(stderr); + return CURLE_ABORTED_BY_CALLBACK; + } + + if (sslctx_cb->debug) { + kmip_debug(sslctx_cb->debug, "Pinned server certificate:"); + X509_print_ex_fp(stderr, cert, XN_FLAG_COMPAT, + X509_FLAG_COMPAT); + } + + rc = X509_STORE_add_cert(store, cert); + if (rc != 1) { + kmip_debug(sslctx_cb->debug, "Failed to add server " + "certificate to SSL Store"); + if (sslctx_cb->debug) + ERR_print_errors_fp(stderr); + X509_free(cert); + return CURLE_ABORTED_BY_CALLBACK; + } + + X509_free(cert); + return CURLE_OK; +} + +/** + * Callback called during curl_easy_perform() to handle received headers. + * Check for the expected response content type. + */ +static size_t mkip_connection_https_header_cb(void *contents, size_t size, + size_t nmemb, void *userp) +{ + struct curl_header_cb_data *cb = (struct curl_header_cb_data *)userp; + size_t num = size * nmemb; + const char *content_type; + char *hdr = contents; + size_t ofs; + char *val; + + if (num < strlen(HTTP_HDR_CONTENT_TYPE)) + goto out; + + if (strncasecmp(hdr, HTTP_HDR_CONTENT_TYPE, + strlen(HTTP_HDR_CONTENT_TYPE)) != 0) + goto out; + + ofs = strlen(HTTP_HDR_CONTENT_TYPE); + val = hdr + ofs; + while (*val == ' ' && ofs < num) { + ofs++; + val++; + } + if (ofs >= num) + goto out; + + switch (cb->conn->config.encoding) { + case KMIP_ENCODING_TTLV: + content_type = "application/octet-stream"; + break; + case KMIP_ENCODING_JSON: + content_type = "application/json"; + break; + case KMIP_ENCODING_XML: + content_type = "text/xml"; + break; + default: + return 0; + } + + if (num - ofs >= strlen(content_type) && + strncasecmp(val, content_type, strlen(content_type)) == 0) + goto out; + + cb->error = true; + kmip_debug(cb->debug, "Unexpected response Content-Type: %.*s", + (int)(num - ofs), val); + return 0; + +out: + return num; +} + + + +/** + * Callback called during curl_easy_perform() to handle received data. + * Parse the (potentially partial) KMIP data. + */ +static size_t mkip_connection_https_write_cb(void *contents, size_t size, + size_t nmemb, void *userp) +{ + struct curl_write_cb_data *cb = (struct curl_write_cb_data *)userp; + enum json_tokener_error jerr; + size_t num = size * nmemb; + int rc; + + switch (cb->conn->config.encoding) { + case KMIP_ENCODING_TTLV: + kmip_debug(cb->debug, "Response Data (TTLV): %lu bytes", num); + if (cb->debug) + kmip_print_dump(__func__, (unsigned char *)contents, + num, 2); + + if (BIO_write(cb->ttlv.resp_mem_bio, contents, num) != + (int)num) { + cb->error = true; + kmip_debug(cb->debug, "BIO_write failed"); + return 0; + } + break; + + case KMIP_ENCODING_JSON: + kmip_debug(cb->debug, "Response Data (JSON):"); + kmip_debug(cb->debug, " ->%*s<-", (int)num, (char *)contents); + + if (cb->json.resp_obj != NULL) { + kmip_debug(cb->debug, "JSON data already complete, but " + "additional data received"); + cb->error = true; + return 0; + } + + cb->json.resp_obj = json_tokener_parse_ex(cb->json.tok, + (const char *)contents, num); + + if (cb->json.resp_obj == NULL) { + jerr = json_tokener_get_error(cb->json.tok); + if (jerr == json_tokener_continue) + goto out; + + cb->error = true; + kmip_debug(cb->debug, "json_tokener_parse_ex failed: %s", + json_tokener_error_desc(jerr)); + return 0; + } + + break; + + case KMIP_ENCODING_XML: + kmip_debug(cb->debug, "Response Data (XML):"); + kmip_debug(cb->debug, " ->%*s<-", (int)num, (char *)contents); + + rc = xmlParseChunk(cb->xml.ctx, (const char *)contents, num, 0); + if (rc != XML_ERR_OK) { + cb->error = true; + kmip_debug(cb->debug, "xmlParseChunk failed: %d", rc); + return 0; + } + break; + } + +out: + return num; +} + + +/** + * Perform a request over the KMIP connection + * + * @param conn the KMIP connection + * @param request the request to send + * @param response On return: the received response. Must be freed by + * the caller. + * + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_connection_https_perform(struct kmip_connection *conn, + struct kmip_node *request, + struct kmip_node **response, + bool debug) +{ + struct curl_sslctx_cb_data sslctx_cb = { 0 }; + struct curl_header_cb_data header_cb = { 0 }; + struct curl_write_cb_data write_cb = { 0 }; + char error_str[CURL_ERROR_SIZE] = { 0 }; + json_object *req_json_obj = NULL; + xmlNode *req_xml_obj = NULL; + xmlDoc *req_xml_doc = NULL; + BIO *req_mem_bio = NULL; + char *req_buff = NULL; + int req_buff_size = 0; + long status_code; + size_t size; + int rc; + + if (conn == NULL || request == NULL || response == NULL) + return -EINVAL; + + *response = NULL; + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_ERRORBUFFER, + error_str); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_ERRORBUFFER", debug, + out); + + /* Setup SSL Context callback */ + sslctx_cb.conn = conn; + sslctx_cb.debug = debug; + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_SSL_CTX_FUNCTION, + mkip_connection_https_sslctx_cb); + CURL_ERROR_CHECK(rc, "curl_easy_setopt " + "CURLOPT_SSL_CTX_FUNCTION", debug, out); + rc = curl_easy_setopt(conn->https.curl, CURLOPT_SSL_CTX_DATA, + &sslctx_cb); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_SSL_CTX_DATA", + debug, out); + + /* Setup write callback to handle received data */ + write_cb.conn = conn; + write_cb.debug = debug; + + switch (conn->config.encoding) { + case KMIP_ENCODING_TTLV: + write_cb.ttlv.resp_mem_bio = BIO_new(BIO_s_mem()); + if (write_cb.ttlv.resp_mem_bio == NULL) { + kmip_debug(debug, "BIO_new failed"); + rc = -ENOMEM; + goto out; + } + break; + + case KMIP_ENCODING_JSON: + write_cb.json.tok = json_tokener_new(); + if (write_cb.json.tok == NULL) { + kmip_debug(debug, "json_tokener_new failed"); + rc = -EIO; + goto out; + } + break; + + case KMIP_ENCODING_XML: + write_cb.xml.ctx = xmlCreatePushParserCtxt(NULL, NULL, NULL, 0, + NULL); + if (write_cb.xml.ctx == NULL) { + kmip_debug(debug, "xmlCreatePushParserCtxt failed"); + rc = -EIO; + goto out; + } + break; + } + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_WRITEFUNCTION, + mkip_connection_https_write_cb); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_WRITEFUNCTION", debug, + out); + rc = curl_easy_setopt(conn->https.curl, CURLOPT_WRITEDATA, + (void *)&write_cb); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_WRITEDATA", debug, + out); + + /* Setup header callback to check content type */ + header_cb.conn = conn; + header_cb.debug = debug; + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_HEADERFUNCTION, + mkip_connection_https_header_cb); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_HEADERFUNCTION", debug, + out); + rc = curl_easy_setopt(conn->https.curl, CURLOPT_HEADERDATA, + (void *)&header_cb); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_HEADERDATA", debug, + out); + + /* Setup POST request and post data */ + rc = curl_easy_setopt(conn->https.curl, CURLOPT_CUSTOMREQUEST, "POST"); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_CUSTOMREQUEST", + debug, out); + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_POST, 1L); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_POST", + debug, out); + + switch (conn->config.encoding) { + case KMIP_ENCODING_TTLV: + req_mem_bio = BIO_new(BIO_s_mem()); + if (req_mem_bio == NULL) { + kmip_debug(debug, "BIO_new failed"); + rc = -ENOMEM; + goto out; + } + + rc = kmip_encode_ttlv(request, req_mem_bio, &size, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_ttlv failed"); + goto out; + } + + req_buff_size = BIO_get_mem_data(req_mem_bio, &req_buff); + + kmip_debug(debug, "Request Data (TTLV): %d bytes", + req_buff_size); + if (debug) + kmip_print_dump(__func__, (unsigned char *)req_buff, + req_buff_size, 2); + break; + + case KMIP_ENCODING_JSON: + rc = kmip_encode_json(request, &req_json_obj, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_json failed"); + goto out; + } + + /* + * The memory returned by json_object_to_json_string_ext + * is freed when the JSON object is freed. + */ + req_buff = (char *)json_object_to_json_string_ext(req_json_obj, + JSON_C_TO_STRING_PLAIN | + JSON_C_TO_STRING_NOSLASHESCAPE); + if (req_buff == NULL) { + kmip_debug(debug, + "json_object_to_json_string_ext failed"); + rc = -EIO; + goto out; + } + req_buff_size = strlen(req_buff); + + kmip_debug(debug, "Request Data (JSON):"); + kmip_debug(debug, " ->%*s<-", req_buff_size, + req_buff); + break; + + case KMIP_ENCODING_XML: + req_xml_doc = xmlNewDoc((xmlChar *)"1.0"); + if (req_xml_doc == NULL) { + kmip_debug(debug, "xmlNewDoc failed"); + rc = -EIO; + goto out; + } + + rc = kmip_encode_xml(request, &req_xml_obj, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_xml failed"); + goto out; + } + + xmlDocSetRootElement(req_xml_doc, req_xml_obj); + req_xml_obj = NULL; + + xmlDocDumpFormatMemoryEnc(req_xml_doc, (xmlChar **)&req_buff, + &req_buff_size, "UTF-8", 0); + if (req_buff == NULL || req_buff_size == 0) { + kmip_debug(debug, "xmlDocDumpFormatMemoryEnc failed"); + rc = -EIO; + goto out; + } + + kmip_debug(debug, "Request Data (XML):"); + kmip_debug(debug, " ->%*s<-", req_buff_size, + req_buff); + break; + } + + rc = curl_easy_setopt(conn->https.curl, CURLOPT_POSTFIELDSIZE, + req_buff_size); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_POSTFIELDSIZE", + debug, out); + rc = curl_easy_setopt(conn->https.curl, CURLOPT_POSTFIELDS, + req_buff); + CURL_ERROR_CHECK(rc, "curl_easy_setopt CURLOPT_POSTFIELDS", + debug, out); + + /* Perform the request */ + rc = curl_easy_perform(conn->https.curl); + if (rc != CURLE_OK) { + kmip_debug(debug, "curl_easy_perform for '%s' failed: %s", + conn->config.server, curl_easy_strerror(rc)); + kmip_debug(debug, "Error: %s", error_str); + + if (header_cb.error) { + kmip_debug(debug, "Unexpected Content-Type"); + rc = -EBADMSG; + } + if (write_cb.error) { + kmip_debug(debug, "JSON/XML parsing failed"); + rc = -EBADMSG; + } + rc = -EIO; + goto out; + } + + /* Check response */ + rc = curl_easy_getinfo(conn->https.curl, CURLINFO_RESPONSE_CODE, + &status_code); + CURL_ERROR_CHECK(rc, "curl_easy_getinfo CURLINFO_RESPONSE_CODE", + debug, out); + kmip_debug(debug, "HTTP status code: %d", status_code); + if (status_code != 200) { + rc = -EBADMSG; + goto out; + } + + /* Process received data */ + switch (conn->config.encoding) { + case KMIP_ENCODING_TTLV: + rc = kmip_decode_ttlv(write_cb.ttlv.resp_mem_bio, NULL, + response, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_decode_ttlv failed"); + goto out; + } + break; + + case KMIP_ENCODING_JSON: + if (write_cb.json.resp_obj == NULL) { + kmip_debug(debug, "JSON content not wellformed"); + rc = -EBADMSG; + goto out; + } + + rc = kmip_decode_json(write_cb.json.resp_obj, NULL, response, + debug); + if (rc != 0) { + kmip_debug(debug, "kmip_decode_json failed"); + goto out; + } + break; + + case KMIP_ENCODING_XML: + rc = xmlParseChunk(write_cb.xml.ctx, "", 0, 1); + if (rc != XML_ERR_OK || !write_cb.xml.ctx->wellFormed || + write_cb.xml.ctx->myDoc == NULL) { + kmip_debug(debug, "XML content not wellformed"); + rc = -EBADMSG; + goto out; + } + + rc = kmip_decode_xml(xmlDocGetRootElement( + write_cb.xml.ctx->myDoc), + NULL, response, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_decode_xml failed"); + goto out; + } + break; + } + + rc = 0; + +out: + /* Cleanup */ + switch (conn->config.encoding) { + case KMIP_ENCODING_TTLV: + if (req_mem_bio != NULL) + BIO_free(req_mem_bio); + if (write_cb.ttlv.resp_mem_bio != NULL) + BIO_free(write_cb.ttlv.resp_mem_bio); + + break; + case KMIP_ENCODING_JSON: + if (write_cb.json.tok != NULL) + json_tokener_free(write_cb.json.tok); + if (write_cb.json.resp_obj != NULL) + json_object_put(write_cb.json.resp_obj); + if (req_json_obj != NULL) + json_object_put(req_json_obj); + break; + case KMIP_ENCODING_XML: + if (write_cb.xml.ctx != NULL) { + xmlFreeDoc(write_cb.xml.ctx->myDoc); + xmlFreeParserCtxt(write_cb.xml.ctx); + } + if (req_xml_doc != NULL) + xmlFreeDoc(req_xml_doc); + if (req_xml_obj != NULL) + xmlFreeNode(req_xml_obj); + if (req_buff != NULL) + xmlFree(req_buff); + break; + } + + if (rc != 0 && *response != NULL) { + kmip_node_free(*response); + *response = NULL; + } + + curl_easy_setopt(conn->https.curl, CURLOPT_SSL_CTX_FUNCTION, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_SSL_CTX_DATA, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_WRITEFUNCTION, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_WRITEDATA, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_HEADERFUNCTION, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_HEADERDATA, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_ERRORBUFFER, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_POSTFIELDS, NULL); + curl_easy_setopt(conn->https.curl, CURLOPT_POSTFIELDSIZE, -1); + + return rc; +} + +/** + * Terminates a HTTPS KMIP connection. + * + * @param conn the KMIP connection to free + */ +void kmip_connection_https_term(struct kmip_connection *conn) +{ + if (conn == NULL) + return; + + if (conn->https.curl != NULL) + curl_easy_cleanup(conn->https.curl); + conn->https.curl = NULL; + + if (conn->https.headers != NULL) + curl_slist_free_all(conn->https.headers); + conn->https.headers = NULL; +} diff --git a/libkmipclient/json.c b/libkmipclient/json.c new file mode 100644 index 00000000..78337192 --- /dev/null +++ b/libkmipclient/json.c @@ -0,0 +1,649 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include +#include + +#include "kmip.h" +#include "names.h" +#include "utils.h" + +#define KMIP_JSON_TAG "tag" +#define KMIP_JSON_NAME "name" +#define KMIP_JSON_TYPE "type" +#define KMIP_JSON_VALUE "value" + +/** + * Decode a KMIP node from the data in a JSON object using the JSON encoding. + * + * @param obj the JSON object to decode + * @param parent the parent node or NULL if no parent exists. + * @param node On return: the decoded node. The newly allocated + * node has a reference count of 1. + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_decode_json(const json_object *obj, struct kmip_node *parent, + struct kmip_node **node, bool debug) +{ + json_object *tag_obj, *type_obj, *value_obj, *name_obj; + enum kmip_tag tag, v1_attr_tag = 0; + enum json_type value_type; + struct kmip_node *n, *e; + const char *str; + int rc, num, i; + int64_t int64; + + if (obj == NULL || node == NULL) + return -EINVAL; + + if (!json_object_is_type(obj, json_type_object)) { + kmip_debug(debug, "Object is not a JSON object"); + return -EINVAL; + } + + n = calloc(1, sizeof(struct kmip_node)); + if (n == NULL) { + kmip_debug(debug, "calloc failed"); + return -ENOMEM; + } + n->ref_count = 1; + + tag_obj = json_object_object_get(obj, KMIP_JSON_TAG); + if (tag_obj == NULL || + !json_object_is_type(tag_obj, json_type_string)) { + kmip_debug(debug, "Missing or invalid '%s' in JSON object", + KMIP_JSON_TAG); + rc = -EBADMSG; + goto out; + } + + str = json_object_get_string(tag_obj); + n->tag = kmip_tag_by_name_or_hex(str); + if (n->tag == 0) { + kmip_debug(debug, "Unknown 'tag' in JSON object: '%s'", str); + rc = -EBADMSG; + goto out; + } + + name_obj = json_object_object_get(obj, KMIP_JSON_NAME); + if (name_obj != NULL) { + if (!json_object_is_type(name_obj, json_type_string)) { + kmip_debug(debug, "Invalid '%s' in JSON object", + KMIP_JSON_NAME); + rc = -EBADMSG; + goto out; + } + n->name = strdup(json_object_get_string(tag_obj)); + } + + type_obj = json_object_object_get(obj, KMIP_JSON_TYPE); + if (type_obj == NULL) { + n->type = KMIP_TYPE_STRUCTURE; + } else { + if (!json_object_is_type(type_obj, json_type_string)) { + kmip_debug(debug, + "Missing or invalid '%s' in JSON object", + KMIP_JSON_TYPE); + rc = -EBADMSG; + goto out; + } + + str = json_object_get_string(type_obj); + n->type = kmip_type_by_name_or_hex(str); + if (n->type == 0) { + kmip_debug(debug, "Unknown 'type' in JSON object: '%s'", + str); + rc = -EBADMSG; + goto out; + } + } + + value_obj = json_object_object_get(obj, KMIP_JSON_VALUE); + if (value_obj == NULL) { + kmip_debug(debug, "Missing '%s' in JSON object", + KMIP_JSON_VALUE); + rc = -EBADMSG; + goto out; + } + value_type = json_object_get_type(value_obj); + + /* + * KMIP v1.x attribute values may be Enumerations or Integer Masks. + * To correctly decode them, we need to know the tag. This is contained + * in a Attribute Name node, which is an element of our parent node. + */ + if (n->tag == KMIP_TAG_ATTRIBUTE_VALUE) + v1_attr_tag = kmip_find_v1_attribute_name_tag(parent); + tag = (v1_attr_tag != 0 ? v1_attr_tag : n->tag); + + kmip_debug(debug, "tag: 0x%x type: 0x%x value_type: %d,", n->tag, + n->type, value_type); + + switch (n->type) { + case KMIP_TYPE_STRUCTURE: + switch (value_type) { + case json_type_null: + break; + case json_type_array: + num = json_object_array_length(value_obj); + for (i = 0; i < num; i++) { + rc = kmip_decode_json( + json_object_array_get_idx(value_obj, i), + n, &e, debug); + if (rc != 0) { + kmip_debug(debug, "Failed to parse " + "array element %d", i); + goto out; + } + rc = kmip_node_add_structure_element(n, e); + kmip_node_free(e); + if (rc != 0) { + kmip_debug(debug, + "kmip_node_structure_add_element " + "failed: rc: %d", rc); + goto out; + } + } + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + case KMIP_TYPE_INTEGER: + case KMIP_TYPE_LONG_INTEGER: + switch (value_type) { + case json_type_int: + case json_type_double: + int64 = json_object_get_int64(value_obj); + break; + case json_type_string: + str = json_object_get_string(value_obj); + if (n->type == KMIP_TYPE_INTEGER && + kmip_is_tag_mask(tag)) { + rc = kmip_parse_mask(tag, str, '|', &int64); + if (rc != 0) { + kmip_debug(debug, "Failed to parse " + "mask string '%s'", str); + goto out; + } + } else { + rc = kmip_parse_hex_int(str, &int64); + if (rc != 0) { + kmip_debug(debug, "Failed to parse " + "hex string '%s'", str); + goto out; + } + } + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + if (n->type == KMIP_TYPE_INTEGER) + n->integer_value = int64; + else + n->long_value = int64; + break; + + case KMIP_TYPE_INTERVAL: + switch (value_type) { + case json_type_int: + case json_type_double: + n->interval_value = json_object_get_int64(value_obj); + break; + case json_type_string: + str = json_object_get_string(value_obj); + rc = kmip_parse_hex_int(str, &int64); + if (rc != 0) { + kmip_debug(debug, "Failed to parse " + "hex string '%s'", str); + goto out; + } + n->interval_value = int64; + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + + case KMIP_TYPE_BIG_INTEGER: + switch (value_type) { + case json_type_int: + case json_type_double: + int64 = htobe64(json_object_get_int64(value_obj)); + rc = kmip_decode_bignum((const unsigned char *)&int64, + sizeof(int64), + &n->big_integer_value); + if (rc != 0) { + kmip_debug(debug, "kmip_decode_bignum failed"); + goto out; + } + break; + case json_type_string: + str = json_object_get_string(value_obj); + rc = kmip_parse_bignum(str, true, + &n->big_integer_value); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse bignum string '%s'", + str); + goto out; + } + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + case KMIP_TYPE_ENUMERATION: + switch (value_type) { + case json_type_int: + case json_type_double: + n->enumeration_value = json_object_get_int64(value_obj); + break; + case json_type_string: + str = json_object_get_string(value_obj); + rc = kmip_enum_value_by_tag_name_or_hex(tag, str, + &n->enumeration_value); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse enumeration '%s'", + str); + goto out; + } + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + case KMIP_TYPE_BOOLEAN: + switch (value_type) { + case json_type_boolean: + n->boolean_value = json_object_get_boolean(value_obj); + break; + case json_type_string: + str = json_object_get_string(value_obj); + rc = kmip_parse_hex_int(str, &int64); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse hex string '%s'", + str); + goto out; + } + n->boolean_value = (int64 != 0); + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + case KMIP_TYPE_TEXT_STRING: + switch (value_type) { + case json_type_string: + n->text_value = strdup( + json_object_get_string(value_obj)); + if (n->text_value == NULL) { + rc = -ENOMEM; + goto out; + } + n->length = strlen(n->text_value); + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + case KMIP_TYPE_BYTE_STRING: + switch (value_type) { + case json_type_string: + str = json_object_get_string(value_obj); + rc = kmip_parse_hex(str, false, &n->bytes_value, + &n->length); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse hex string '%s'", + str); + goto out; + } + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + case KMIP_TYPE_DATE_TIME: + switch (value_type) { + case json_type_int: + case json_type_double: + n->date_time_value = json_object_get_int64(value_obj); + break; + case json_type_string: + str = json_object_get_string(value_obj); + rc = kmip_parse_timestamp(str, &n->date_time_value); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse time stamp '%s'", + str); + goto out; + } + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + case KMIP_TYPE_DATE_TIME_EXTENDED: + switch (value_type) { + case json_type_int: + case json_type_double: + n->date_time_ext_value = + json_object_get_int64(value_obj); + break; + case json_type_string: + str = json_object_get_string(value_obj); + rc = kmip_parse_hex_int(str, &int64); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse hex string '%s'", + str); + goto out; + } + n->date_time_ext_value = int64; + break; + default: + kmip_debug(debug, "Invalid JSON type %d for node type " + "0x%x", value_type, n->type); + rc = -EBADMSG; + goto out; + } + break; + + default: + kmip_debug(debug, "unknown type: 0x%x", n->type); + rc = -EBADMSG; + goto out; + } + + *node = n; + rc = 0; + +out: + if (rc != 0) + kmip_node_free(n); + return rc; +} + +/** + * Encode a KMIP node into a JSON object using the JSON encoding. + * + * @param node the node to encode + * @param obj On return: the JSON object + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_encode_json(const struct kmip_node *node, json_object **obj, + bool debug) +{ + json_object *ret_obj = NULL, *memb_obj, *elem_obj; + enum kmip_tag tag, v1_attr_tag = 0; + struct kmip_node *element; + char outstr[200] = { 0 }; + const char *str; + int64_t int64; + struct tm *tm; + char *tmp; + char *s; + int rc; + + if (node == NULL || obj == NULL) + return -EINVAL; + + kmip_debug(debug, "tag: 0x%x type: 0x%x", node->tag, node->type); + + ret_obj = json_object_new_object(); + if (ret_obj == NULL) { + kmip_debug(debug, "Failed to allocate a JSON object"); + return -ENOMEM; + } + + memb_obj = json_object_new_string( + kmip_tag_name_or_hex_by_tag(node->tag, + outstr)); + if (memb_obj == NULL) { + kmip_debug(debug, "Failed to build JSON object for tag"); + rc = -ENOMEM; + goto out; + } + rc = json_object_object_add(ret_obj, KMIP_JSON_TAG, memb_obj); + if (rc != 0) { + kmip_debug(debug, "Failed to add JSON object for tag"); + rc = -EIO; + goto out; + } + + if (node->name != NULL) { + memb_obj = json_object_new_string(node->name); + if (memb_obj == NULL) { + kmip_debug(debug, + "Failed to build JSON object for name"); + rc = -ENOMEM; + goto out; + } + rc = json_object_object_add(ret_obj, KMIP_JSON_NAME, memb_obj); + if (rc != 0) { + kmip_debug(debug, "Failed to add JSON object for name"); + rc = -EIO; + goto out; + } + } + + if (node->type != KMIP_TYPE_STRUCTURE) { + str = kmip_type_name_by_type(node->type); + if (str == NULL) { + kmip_debug(debug, "unknown type 0x%x", node->type); + rc = -EINVAL; + goto out; + } + memb_obj = json_object_new_string(str); + if (memb_obj == NULL) { + kmip_debug(debug, + "Failed to build JSON object for type"); + rc = -ENOMEM; + goto out; + } + rc = json_object_object_add(ret_obj, KMIP_JSON_TYPE, memb_obj); + if (rc != 0) { + kmip_debug(debug, "Failed to add JSON object for type"); + rc = -EIO; + goto out; + } + } + + /* + * KMIP v1.x attribute values may be Enumerations or Integer Masks. + * To correctly encode them, we need to know the tag. This is contained + * in a Attribute Name node, which is an element of our parent node. + */ + if (node->tag == KMIP_TAG_ATTRIBUTE_VALUE) + v1_attr_tag = kmip_find_v1_attribute_name_tag(node->parent); + tag = (v1_attr_tag != 0 ? v1_attr_tag : node->tag); + + switch (node->type) { + case KMIP_TYPE_STRUCTURE: + memb_obj = json_object_new_array(); + if (memb_obj == NULL) { + kmip_debug(debug, + "Failed to build JSON object for value array"); + rc = -ENOMEM; + goto out; + } + element = node->structure_value; + while (element != NULL) { + rc = kmip_encode_json(element, &elem_obj, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_json failed"); + goto out; + } + rc = json_object_array_add(memb_obj, elem_obj); + if (rc != 0) { + kmip_debug(debug, + "json_object_array_add failed"); + rc = EIO; + goto out; + } + element = element->next; + } + break; + + case KMIP_TYPE_INTEGER: + if (kmip_is_tag_mask(tag) && node->integer_value != 0) { + rc = kmip_format_mask(tag, node->integer_value, + '|', &tmp); + if (rc != 0) { + kmip_debug(debug, "kmip_format_mask failed"); + goto out; + } + memb_obj = json_object_new_string(tmp); + free(tmp); + } else { + memb_obj = json_object_new_int(node->integer_value); + } + break; + + case KMIP_TYPE_INTERVAL: + memb_obj = json_object_new_int(node->interval_value); + break; + + case KMIP_TYPE_LONG_INTEGER: + case KMIP_TYPE_DATE_TIME_EXTENDED: + if (node->type == KMIP_TYPE_LONG_INTEGER) + int64 = node->long_value; + else + int64 = node->date_time_ext_value; + /* any values >= 2^52 must be represented as hex strings */ + if (int64 < 4503599627370496 && + int64 > -4503599627370496) { + memb_obj = json_object_new_int64(int64); + } else { + rc = kmip_format_hex((const unsigned char *)&int64, + sizeof(int64), true, &tmp); + if (rc != 0) { + kmip_debug(debug, "kmip_format_hex failed"); + goto out; + } + memb_obj = json_object_new_string(tmp); + free(tmp); + } + break; + + case KMIP_TYPE_BIG_INTEGER: + rc = kmip_format_bignum(node->big_integer_value, true, &s); + if (rc != 0) { + kmip_debug(debug, "kmip_format_bignum failed"); + goto out; + } + memb_obj = json_object_new_string(s); + free(s); + break; + + case KMIP_TYPE_ENUMERATION: + str = kmip_enum_name_by_tag_value(tag, node->enumeration_value); + if (str != NULL) + memb_obj = json_object_new_string(str); + else + memb_obj = json_object_new_int(node->enumeration_value); + break; + + case KMIP_TYPE_BOOLEAN: + memb_obj = json_object_new_boolean(node->boolean_value); + break; + + case KMIP_TYPE_TEXT_STRING: + memb_obj = json_object_new_string(node->text_value); + break; + + case KMIP_TYPE_BYTE_STRING: + rc = kmip_format_hex(node->bytes_value, node->length, + false, &s); + if (rc != 0) { + kmip_debug(debug, "kmip_format_hex_long failed"); + goto out; + } + memb_obj = json_object_new_string(s); + free(s); + break; + + case KMIP_TYPE_DATE_TIME: + tm = gmtime((time_t *)&node->date_time_value); + strftime(outstr, sizeof(outstr), KMIP_ISO8601_TIMESTAMP_UTC, + tm); + memb_obj = json_object_new_string(outstr); + break; + + default: + kmip_debug(debug, "unknown type: 0x%x", node->type); + rc = -EINVAL; + goto out; + } + + if (memb_obj == NULL) { + rc = -ENOMEM; + goto out; + } + + rc = json_object_object_add(ret_obj, KMIP_JSON_VALUE, memb_obj); + if (rc != 0) { + kmip_debug(debug, "Failed to add JSON object for value"); + rc = -EIO; + goto out; + } + + rc = 0; + *obj = ret_obj; + +out: + if (rc != 0) + json_object_put(ret_obj); + + return rc; +} + diff --git a/libkmipclient/key.c b/libkmipclient/key.c new file mode 100644 index 00000000..d701e036 --- /dev/null +++ b/libkmipclient/key.c @@ -0,0 +1,1439 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include +#include +#include +#include + +#include "kmip.h" +#include "names.h" + +/** + * Constructs a Key Block node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Block Structure v1.0 + * Key Format Type Yes Enumeration v1.0 + * Key Compression Type No Enumeration v1.0 + * Key Value Yes various v1.0 + * Cryptographic Algorithm Yes Enumeration v1.0 + * Cryptographic Length Yes Integer v1.0 + * Key Wrapping Data No Structure v1.0 + * + * @param format_type the key format type + * @param format_type the key compression type (if 0 it is ignored) + * @param key_value the key value node + * @param algorithm the key algorithm (if 0 it is ignored) + * @param length the cryptographic length (if <= 0 it is ignored) + * @param wrappig_data the key wrapping data (can be NULL) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_key_block(enum kmip_key_format_type format_type, + enum kmip_key_compression_type compr_type, + struct kmip_node *key_value, + enum kmip_crypto_algo algorithm, + int32_t length, + struct kmip_node *wrappig_data) +{ + struct kmip_node *ret = NULL, *fmt, *cmp = NULL, *algo = NULL; + struct kmip_node *len = NULL; + + if (format_type == 0 || key_value == NULL) + return NULL; + + fmt = kmip_node_new_enumeration(KMIP_TAG_KEY_FORMAT_TYPE, NULL, + format_type); + if (fmt == NULL) + goto out; + + if (compr_type != 0) { + cmp = kmip_node_new_enumeration(KMIP_TAG_KEY_COMPRESSION_TYPE, + NULL, compr_type); + if (cmp == NULL) + goto out; + } + + if (algorithm != 0) { + algo = kmip_node_new_enumeration( + KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, + NULL, algorithm); + if (algo == NULL) + goto out; + } + + if (length > 0) { + len = kmip_node_new_integer(KMIP_TAG_CRYPTOGRAPHIC_LENGTH, NULL, + length); + if (len == NULL) + goto out; + } + + ret = kmip_node_new_structure_va(KMIP_TAG_KEY_BLOCK, NULL, 6, fmt, cmp, + key_value, algo, len, wrappig_data); + +out: + kmip_node_free(fmt); + kmip_node_free(cmp); + kmip_node_free(algo); + kmip_node_free(len); + + return ret; +} + +/** + * Gets information from a Key Block node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Block Structure v1.0 + * Key Format Type Yes Enumeration v1.0 + * Key Compression Type No Enumeration v1.0 + * Key Value Yes various v1.0 + * Cryptographic Algorithm Yes Enumeration v1.0 + * Cryptographic Length Yes Integer v1.0 + * Key Wrapping Data No Structure v1.0 + * + * @param node the KMIP node + * @param format_type On return: the key format type + * @param format_type On return: the key compression type (0 if not avail, + * can be NULL) + * @param key_value On return: the key value node (can be NULL) + * @param algorithm On return: the key algorithm (0 if not avail, can + * be NULL) + * @param length On return: the cryptographic length (0 if not avail, + * can be NULL) + * @param wrappig_data On return: the key wrapping data (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_key_block(const struct kmip_node *node, + enum kmip_key_format_type *format_type, + enum kmip_key_compression_type *compr_type, + struct kmip_node **key_value, + enum kmip_crypto_algo *algorithm, + int32_t *length, + struct kmip_node **wrappig_data) +{ + struct kmip_node *n; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_BLOCK) + return -EBADMSG; + + if (format_type != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_FORMAT_TYPE, 0); + if (n == NULL) + return -EBADMSG; + *format_type = kmip_node_get_enumeration(n); + kmip_node_free(n); + } + + if (compr_type != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_COMPRESSION_TYPE, 0); + if (n != NULL) + *compr_type = kmip_node_get_enumeration(n); + else + *compr_type = 0; + kmip_node_free(n); + } + + if (algorithm != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, 0); + if (n != NULL) + *algorithm = kmip_node_get_enumeration(n); + else + *algorithm = 0; + kmip_node_free(n); + } + + if (length != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_CRYPTOGRAPHIC_LENGTH, 0); + if (n != NULL) + *length = kmip_node_get_integer(n); + else + *length = -1; + kmip_node_free(n); + } + + if (key_value != NULL) { + *key_value = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_VALUE, 0); + if (*key_value == NULL) + return -EBADMSG; + } + + if (wrappig_data != NULL) + *wrappig_data = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_WRAPPING_DATA, 0); + + return 0; +} + +/** + * Constructs a Key Value node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Value Structure v1.0 + * Key Material Yes various v1.0 + * Attribute No Structure v1.x only + * ... may be repeated + * Attributes No Structure v2.x only + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param key_material the key material node + * @param attrs_count the number of attributes following (can be 0) + * @param v2_attrs the array of attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_key_value(const struct kmip_version *version, + struct kmip_node *key_material, + unsigned int attrs_count, + struct kmip_node **v2_attrs) +{ + struct kmip_node *ret = NULL, *v2_attr, *v1_attr, *attrs = NULL; + unsigned int i; + int rc; + + if (key_material == NULL) + return NULL; + if (attrs_count > 0 && v2_attrs == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + if (version->major == 1) { + /* KMIP v1.x */ + ret = kmip_node_new_structure_va(KMIP_TAG_KEY_VALUE, NULL, 1, + key_material); + if (ret == NULL) + return NULL; + + for (i = 0; i < attrs_count; i++) { + v2_attr = v2_attrs[i]; + if (v2_attr == NULL) + continue; + + rc = kmip_v1_attr_from_v2_attr(v2_attr, &v1_attr); + if (rc != 0) + goto error; + + rc = kmip_node_add_structure_element(ret, v1_attr); + kmip_node_free(v1_attr); + if (rc != 0) + goto error; + } + } else { + /* KMIP >= v2.0 */ + if (attrs_count > 0) { + attrs = kmip_new_attributes(version, + KMIP_TAG_ATTRIBUTES, + attrs_count, v2_attrs); + if (attrs == NULL) + return NULL; + } + + ret = kmip_node_new_structure_va(KMIP_TAG_KEY_VALUE, NULL, 2, + key_material, attrs); + kmip_node_free(attrs); + } + + return ret; + +error: + kmip_node_free(ret); + return NULL; +} + +/** + * Constructs a Key Value node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Value Structure v1.0 + * Key Material Yes various v1.0 + * Attribute No Structure v1.x only + * ... may be repeated + * Attributes No Structure v2.x only + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param key_material the key material node + * @param attrs_count the number of attributes following (can be 0) + * @param the attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_key_value_va(const struct kmip_version *version, + struct kmip_node *key_material, + unsigned int attrs_count, ...) +{ + struct kmip_node *ret, **attrs = NULL; + unsigned int i, k; + va_list ap; + + if (attrs_count > 0) { + attrs = calloc(attrs_count, sizeof(struct kmip_node *)); + if (attrs == NULL) + return NULL; + } + + va_start(ap, attrs_count); + for (i = 0, k = 0; i < attrs_count; i++) { + attrs[k] = va_arg(ap, struct kmip_node *); + if (attrs[k] != NULL) + k++; + } + va_end(ap); + + ret = kmip_new_key_value(version, key_material, k, attrs); + if (attrs != NULL) + free(attrs); + + return ret; +} + +/** + *Gets information from a Key Value node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Value (wrapped key value) Byte String v1.0 + * Key Value (plaintext key value) Structure v1.0 + * Key Material Yes various v1.0 + * Attribute No Structure v1.x only + * ... may be repeated + * Attributes No Structure v2.x only + * + * @param node the KMIP node + * @param key_material On return: the key material node (can be NULL) + * @param num_attrs On return: the number of attributes (can be NULL). + * @param index the index of the attribute to get + * @param v2_attr On return: the attribute (as v2.x attribute) at the + * specified index. Function returns -ENOENT if no + * attribute is available at the index. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_key_value(const struct kmip_node *node, + struct kmip_node **key_material, + unsigned int *num_attrs, unsigned int index, + struct kmip_node **v2_attr) +{ + struct kmip_node *attr; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_VALUE) + return -EBADMSG; + + if (key_material != NULL) { + switch (kmip_node_get_type(node)) { + case KMIP_TYPE_BYTE_STRING: + /* Wrapped key value */ + *key_material = (struct kmip_node *)node; + kmip_node_upref(*key_material); + break; + + case KMIP_TYPE_STRUCTURE: + /* plaintext key value */ + *key_material = + kmip_node_get_structure_element_by_index(node, + 0); + if (*key_material == NULL) + return -EBADMSG; + + switch (kmip_node_get_type(*key_material)) { + case KMIP_TYPE_BYTE_STRING: + /* Raw, Opaque, PKCS1, PKCS8, ECPrivateKey */ + break; + case KMIP_TYPE_STRUCTURE: + /* Transparent key formats */ + switch (kmip_node_get_tag(*key_material)) { + /* Transparent key formats: TAG_KEY_MATERIAL */ + case KMIP_TAG_KEY_MATERIAL: + break; + default: + rc = -EBADMSG; + goto error; + } + break; + default: + rc = -EBADMSG; + goto error; + } + break; + + default: + return -EBADMSG; + } + } + + if (v2_attr == NULL || kmip_node_get_type(node) != KMIP_TYPE_STRUCTURE) + return 0; + + attr = kmip_node_get_structure_element_by_index(node, 1); + if (attr == NULL) { + rc = -ENOENT; + goto error; + } + + if (kmip_node_get_tag(attr) == KMIP_TAG_ATTRIBUTES) { + /* Its already a KMIP v2.x attributes structure */ + rc = kmip_get_attributes(attr, num_attrs, index, v2_attr); + kmip_node_free(attr); + if (rc != 0) + goto error; + return 0; + } + + /* Must be a KMIP v1.x attribute then */ + kmip_node_free(attr); + + if (num_attrs != NULL) + *num_attrs = kmip_node_get_structure_element_count(node) - 1; + + if (v2_attr == NULL) + return 0; + + attr = kmip_node_get_structure_element_by_index(node, index + 1); + if (attr == NULL) { + rc = -ENOENT; + goto error; + } + + rc = kmip_v2_attr_from_v1_attr(attr, v2_attr); + kmip_node_free(attr); + if (rc != 0) + goto error; + + return 0; + +error: + if (key_material != NULL) { + kmip_node_free(*key_material); + *key_material = NULL; + } + + return rc; +} + +/** + * Constructs a Key Wrapping Data node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Wrapping Data Structure v1.0 + * Wrapping Method Yes Enumeration v1.0 + * Encryption Key Information No Structure v1.0 + * MAC/Signature Key Info. No Structure v1.0 + * MAC/Signature No Byte String v1.0 + * IV/Counter/Nonce No Byte String v1.0 + * Encoding Option No Enumeration v1.2 + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param wrap_method the key wrapping method + * @param encr_key_info the encryption key info node (can be NULL) + * @param mac_sign_key_info the MAC/Sign key info node (can be NULL) + * @param mac_signature MAC/signature (can be NULL) + * @param mac_signature_len the length of the MAC/Signature + * @param iv_counter_nonce IV/Counter/Nonce (can be NULL) + * @param iv_counter_nonce_len the length of theIV/Counter/Nonce + * @param encoding the encoding option (can be 0, defaults to TTLV) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_key_wrapping_data( + const struct kmip_version *version, + enum kmip_wrapping_method wrap_method, + struct kmip_node *encr_key_info, + struct kmip_node *mac_sign_key_info, + const unsigned char *mac_signature, + uint32_t mac_signature_len, + const unsigned char *iv_counter_nonce, + uint32_t iv_counter_nonce_len, + enum kmip_encoding_option encoding) +{ + struct kmip_node *ret = NULL, *wmeth, *mac = NULL, *iv = NULL; + struct kmip_node *enc = NULL; + + if (wrap_method == 0) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + wmeth = kmip_node_new_enumeration(KMIP_TAG_WRAPPING_METHOD, NULL, + wrap_method); + if (wmeth == NULL) + goto out; + + if (mac_signature != NULL && mac_signature_len > 0) { + mac = kmip_node_new_byte_string(KMIP_TAG_MAC_SIGNATURE, + NULL, mac_signature, + mac_signature_len); + if (mac == NULL) + goto out; + } + + if (iv_counter_nonce != NULL && iv_counter_nonce_len > 0) { + iv = kmip_node_new_byte_string(KMIP_TAG_IV_COUNTER_NONCE, + NULL, iv_counter_nonce, + iv_counter_nonce_len); + if (iv == NULL) + goto out; + } + + if (encoding != 0 && (version->major > 1 || + (version->major == 1 && version->minor > 1))) { + enc = kmip_node_new_enumeration(KMIP_TAG_ENCODING_OPTION, NULL, + encoding); + if (enc == NULL) + goto out; + } + + ret = kmip_node_new_structure_va(KMIP_TAG_KEY_WRAPPING_DATA, NULL, 6, + wmeth, encr_key_info, + mac_sign_key_info, mac, iv, enc); + +out: + kmip_node_free(wmeth); + kmip_node_free(mac); + kmip_node_free(iv); + kmip_node_free(enc); + + return ret; +} + +/** + *Gets information from a Key Wrapping Data node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Wrapping Data Structure v1.0 + * Wrapping Method Yes Enumeration v1.0 + * Encryption Key Information No Structure v1.0 + * MAC/Signature Key Info. No Structure v1.0 + * MAC/Signature No Byte String v1.0 + * IV/Counter/Nonce No Byte String v1.0 + * Encoding Option No Enumeration v1.2 + * + * @param node the KMIP node + * @param wrap_method On return: the key wrapping method (can be NULL) + * @param encr_key_info On return: the encryption key info node + * (can be NULL) + * @param mac_sign_key_info On return: the MAC/Sign key info node (can be NULL) + * @param mac_signature On return: MAC/signature (can be NULL) + * @param mac_signature_len On return: the length of the MAC/Signature + * (can be NULL) + * @param iv_counter_nonce On return: IV/Counter/Nonce (can be NULL) + * @param iv_counter_nonce_len On return: the length of theIV/Counter/Nonce + * (can be NULL) + * @param encoding On return: the encoding option (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_key_wrapping_data(const struct kmip_node *node, + enum kmip_wrapping_method *wrap_method, + struct kmip_node **encr_key_info, + struct kmip_node **mac_sign_key_info, + const unsigned char **mac_signature, + uint32_t *mac_signature_len, + const unsigned char **iv_counter_nonce, + uint32_t *iv_counter_nonce_len, + enum kmip_encoding_option *encoding) +{ + struct kmip_node *n; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_WRAPPING_DATA) + return -EBADMSG; + + if (wrap_method != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_WRAPPING_METHOD, 0); + if (n == NULL) + return -EBADMSG; + *wrap_method = kmip_node_get_enumeration(n); + kmip_node_free(n); + } + + if (mac_signature != NULL && mac_signature_len != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_MAC_SIGNATURE, 0); + if (n != NULL) { + *mac_signature = kmip_node_get_byte_string(n, + mac_signature_len); + } else { + *mac_signature = NULL; + *mac_signature_len = 0; + } + kmip_node_free(n); + } + + if (iv_counter_nonce != NULL && iv_counter_nonce_len != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_IV_COUNTER_NONCE, 0); + if (n != NULL) { + *iv_counter_nonce = kmip_node_get_byte_string(n, + iv_counter_nonce_len); + } else { + *iv_counter_nonce = NULL; + *iv_counter_nonce_len = 0; + } + kmip_node_free(n); + } + + if (encoding != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ENCODING_OPTION, 0); + + *encoding = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (encr_key_info != NULL) + *encr_key_info = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ENCRYPTION_KEY_INFORMATION, 0); + + if (mac_sign_key_info != NULL) + *mac_sign_key_info = + kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_MAC_SIGNATURE_KEY_INFORMATION, 0); + + return 0; +} + +/** + * Constructs a Key Wrapping Specification node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Wrapping Specification Structure v1.0 + * Wrapping Method Yes Enumeration v1.0 + * Encryption Key Information No Structure v1.0 + * MAC/Signature Key Info. No Structure v1.0 + * Attribute Name No Text String v1.0 + * ... may be repeated + * Encoding Option No Enumeration v1.2 + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param wrap_method the key wrapping method + * @param encr_key_info the encryption key info node (can be NULL) + * @param mac_sign_key_info the MAC/Sign key info node (can be NULL) + * @param encoding the encoding option (can be 0, defaults to TTLV) + * @param attr_name_count the number of attribute names following + * @param attr_names the array of attributes names (as const char *) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_key_wrapping_specification( + const struct kmip_version *version, + enum kmip_wrapping_method wrap_method, + struct kmip_node *encr_key_info, + struct kmip_node *mac_sign_key_info, + enum kmip_encoding_option encoding, + unsigned int attr_name_count, + const char **attr_names) +{ + struct kmip_node *ret = NULL, *wmeth, *enc = NULL, *name; + unsigned int i; + int rc; + + if (wrap_method == 0) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + wmeth = kmip_node_new_enumeration(KMIP_TAG_WRAPPING_METHOD, NULL, + wrap_method); + if (wmeth == NULL) + goto out; + + ret = kmip_node_new_structure_va(KMIP_TAG_KEY_WRAPPING_SPECIFICATION, + NULL, 3, wmeth, encr_key_info, + mac_sign_key_info); + + + for (i = 0; i < attr_name_count; i++) { + if (attr_names[i] == NULL) + continue; + + name = kmip_node_new_text_string(KMIP_TAG_ATTRIBUTE_NAME, NULL, + attr_names[i]); + if (name == NULL) + goto error; + + rc = kmip_node_add_structure_element(ret, name); + kmip_node_free(name); + if (rc != 0) + goto error; + } + + if (encoding != 0 && (version->major > 1 || + (version->major == 1 && version->minor > 1))) { + enc = kmip_node_new_enumeration(KMIP_TAG_ENCODING_OPTION, NULL, + encoding); + if (enc == NULL) + goto error; + + rc = kmip_node_add_structure_element(ret, enc); + if (rc != 0) + goto error; + } + goto out; + +error: + kmip_node_free(ret); + ret = NULL; + +out: + kmip_node_free(wmeth); + kmip_node_free(enc); + + return ret; +} + +/** + * Constructs a Key Wrapping Specification node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Wrapping Specification Structure v1.0 + * Wrapping Method Yes Enumeration v1.0 + * Encryption Key Information No Structure v1.0 + * MAC/Signature Key Info. No Structure v1.0 + * Attribute Name No Text String v1.0 + * ... may be repeated + * Encoding Option No Enumeration v1.2 + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param wrap_method the key wrapping method + * @param encr_key_info the encryption key info node (can be NULL) + * @param mac_sign_key_info the MAC/Sign key info node (can be NULL) + * @param encoding the encoding option (can be 0, defaults to TTLV) + * @param attr_name_count the number of atribute names following + * @param the attributes names (as const char *) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_key_wrapping_specification_va( + const struct kmip_version *version, + enum kmip_wrapping_method wrap_method, + struct kmip_node *encr_key_info, + struct kmip_node *mac_sign_key_info, + enum kmip_encoding_option encoding, + unsigned int attr_name_count, ...) +{ + const char **names = NULL; + struct kmip_node *ret; + unsigned int i; + va_list ap; + + if (attr_name_count > 0) { + names = calloc(attr_name_count, sizeof(const char *)); + if (names == NULL) + return NULL; + } + + va_start(ap, attr_name_count); + for (i = 0; i < attr_name_count; i++) + names[i] = va_arg(ap, const char *); + va_end(ap); + + ret = kmip_new_key_wrapping_specification(version, wrap_method, + encr_key_info, + mac_sign_key_info, encoding, + attr_name_count, names); + if (names != NULL) + free(names); + + return ret; +} + + +/** + *Gets information from a Key Wrapping Specification node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Wrapping Specification Structure v1.0 + * Wrapping Method Yes Enumeration v1.0 + * Encryption Key Information No Structure v1.0 + * MAC/Signature Key Info. No Structure v1.0 + * Attribute Name No Text String v1.0 + * ... may be repeated + * Encoding Option No Enumeration v1.2 + + * + * @param node the KMIP node + * @param wrap_method On return: the key wrapping method (can be NULL) + * @param encr_key_info On return: the encryption key info node + * (can be NULL) + * @param mac_sign_key_info On return: the MAC/Sign key info node (can be NULL) + * @param encoding On return: the encoding option (can be NULL) + * @param num_attr_names On return: the number of attributes (can be NULL). + * @param attr_name_index The index of the attribute name to return + * @param attr_name On return: the attribute name at the specified index + * (can be NULL). Function returns -ENOENT if no name + * is available at the index. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_key_wrapping_specification(const struct kmip_node *node, + enum kmip_wrapping_method *wrap_method, + struct kmip_node **encr_key_info, + struct kmip_node **mac_sign_key_info, + enum kmip_encoding_option *encoding, + unsigned int *num_attr_names, + unsigned int attr_name_index, + const char **attr_name) +{ + struct kmip_node *n; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_WRAPPING_SPECIFICATION) + return -EBADMSG; + + if (wrap_method != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_WRAPPING_METHOD, 0); + if (n == NULL) + return -EBADMSG; + *wrap_method = kmip_node_get_enumeration(n); + kmip_node_free(n); + } + + if (encoding != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ENCODING_OPTION, 0); + *encoding = (n != NULL ? kmip_node_get_enumeration(n) : 0); + kmip_node_free(n); + } + + if (num_attr_names != NULL) + *num_attr_names = kmip_node_get_structure_element_by_tag_count( + node, KMIP_TAG_ATTRIBUTE_NAME); + + if (attr_name != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ATTRIBUTE_NAME, attr_name_index); + if (n == NULL) + return -ENOENT; + *attr_name = kmip_node_get_text_string(n); + kmip_node_free(n); + } + + if (encr_key_info != NULL) + *encr_key_info = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ENCRYPTION_KEY_INFORMATION, 0); + + if (mac_sign_key_info != NULL) + *mac_sign_key_info = + kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_MAC_SIGNATURE_KEY_INFORMATION, 0); + + return 0; +} + + +/** + * Constructs a Encryption Key Information or MAC/Signature Key Information + * node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Information Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Cryptographic Parameters No Structure v1.0 + * + * @param mac_sign if true a MAC/Signature Key Information node is + * created, otherwise a Encryption Key Information + * node. + * @param unique_id the unique ID node + * @param crypto_params the cryptographic parameters node (can be NULL) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_key_info(bool mac_sign, struct kmip_node *unique_id, + struct kmip_node *crypto_params) +{ + enum kmip_tag tag; + + if (unique_id == NULL) + return NULL; + + tag = (mac_sign ? KMIP_TAG_MAC_SIGNATURE_KEY_INFORMATION : + KMIP_TAG_ENCRYPTION_KEY_INFORMATION); + return kmip_node_new_structure_va(tag, NULL, 2, unique_id, + crypto_params); +} + +/** + * Gets the information from an Encryption Key Information or MAC/Signature Key + * Information node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Information Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Cryptographic Parameters No Structure v1.0 + * + * @param node the KMIP node + * @param unique_id On return: the unique ID node (can be NULL) + * @param crypto_params On return: the cryptographic parameters node (can + * be NULL) + * + * @returns 0 on success, or a negative errno in case of an error + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_key_info(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **crypto_params) +{ + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_ENCRYPTION_KEY_INFORMATION && + kmip_node_get_tag(node) != KMIP_TAG_MAC_SIGNATURE_KEY_INFORMATION) + return -EBADMSG; + + if (unique_id != NULL) { + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, 0); + if (*unique_id == NULL) + return -EBADMSG; + } + + if (crypto_params != NULL) + *crypto_params = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS, 0); + + return 0; +} + +/** + * Constructs a Transparent Symmetric Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Structure v1.0 + * Key Yes Byte String v1.0 + * + * @param key the key + * @param key_length the key length + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_transparent_symmetric_key(const unsigned char *key, + uint32_t key_length) +{ + struct kmip_node *k, *ret; + + if (key == NULL || key_length == 0) + return NULL; + + k = kmip_node_new_byte_string(KMIP_TAG_KEY, NULL, key, key_length); + if (k == NULL) + return NULL; + + ret = kmip_node_new_structure_va(KMIP_TAG_KEY_MATERIAL, NULL, 1, k); + kmip_node_free(k); + + return ret; +} + +/** + * Gets the information from a Transparent Symmetric Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Structure v1.0 + * Key Yes Byte String v1.0 + * + * @param node the KMIP node + * @param key On return: the key + * @param key_length On return: the key length + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_transparent_symmetric_key(const struct kmip_node *node, + const unsigned char **key, + uint32_t *key_length) +{ + struct kmip_node *k; + + if (node == NULL || key == NULL || key_length == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_MATERIAL) + return -EBADMSG; + + k = kmip_node_get_structure_element_by_tag(node, KMIP_TAG_KEY, 0); + if (k == NULL) + return -EBADMSG; + + *key = kmip_node_get_byte_string(k, key_length); + kmip_node_free(k); + + return 0; +} + +/** + * Constructs a Transparent RSA Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Structure v1.0 + * Modulus Yes Big Integer v1.0 + * Public Exponent Yes Big Integer v1.0 + * + * @param modulus the modulus as OpenSSL BIGNUM + * @param pub_ext the public exponent as OpenSSL BIGNUM + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_transparent_rsa_public_key(const BIGNUM *modulus, + const BIGNUM *pub_exp) +{ + struct kmip_node *mod, *exp, *ret = NULL; + + if (modulus == NULL || pub_exp == NULL) + return NULL; + + mod = kmip_node_new_bigint(KMIP_TAG_MODULUS, NULL, modulus); + exp = kmip_node_new_bigint(KMIP_TAG_PUBLIC_EXPONENT, NULL, pub_exp); + if (mod == NULL || exp == NULL) + goto out; + + ret = kmip_node_new_structure_va(KMIP_TAG_KEY_MATERIAL, NULL, 2, mod, + exp); + +out: + kmip_node_free(mod); + kmip_node_free(exp); + + return ret; +} + +/** + * Gets the information from a Transparent RSA Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Structure v1.0 + * Modulus Yes Big Integer v1.0 + * Public Exponent Yes Big Integer v1.0 + * + * @param node the KMIP node + * @param modulus On return: the modulus as OpenSSL BIGNUM + * @param pub_ext On return: the public exponent as OpenSSL BIGNUM + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_transparent_rsa_public_key(const struct kmip_node *node, + const BIGNUM **modulus, + const BIGNUM **pub_exp) +{ + struct kmip_node *n; + + if (node == NULL || modulus == NULL || pub_exp == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_MATERIAL) + return -EBADMSG; + + n = kmip_node_get_structure_element_by_tag(node, KMIP_TAG_MODULUS, 0); + if (n == NULL) + return -EBADMSG; + *modulus = kmip_node_get_bigint(n); + kmip_node_free(n); + + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_PUBLIC_EXPONENT, 0); + if (n == NULL) + return -EBADMSG; + *pub_exp = kmip_node_get_bigint(n); + kmip_node_free(n); + + return 0; +} + +/** + * Constructs a PKCS#1 Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Byte String v1.0 + * + * @param pub_key the public key as OpenSSL PKEY + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_pkcs1_public_key(EVP_PKEY *pub_key) +{ + struct kmip_node *ret = NULL; + unsigned char *buf = NULL; + int len; + + if (pub_key == NULL) + return NULL; + + len = i2d_PublicKey(pub_key, &buf); + if (len <= 0) + return NULL; + + ret = kmip_node_new_byte_string(KMIP_TAG_KEY_MATERIAL, NULL, buf, len); + + OPENSSL_free(buf); + return ret; +} + +/** + * Gets the information from a PKCS#1 Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Byte String v1.0 + * + * @param node the KMIP node + * @param algo the algorithm of the key + * @param pub_key On return: the public key as OpenSSL PKEY. Must be + * freed by the caller using EVP_PKEY_free() when no + * longer needed. + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_pkcs1_public_key(const struct kmip_node *node, + enum kmip_crypto_algo algo, + EVP_PKEY **pub_key) +{ + const unsigned char *buf; + uint32_t len = 0; + int type; + + if (node == NULL || pub_key == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_MATERIAL) + return -EBADMSG; + + buf = kmip_node_get_byte_string(node, &len); + if (buf == NULL || len == 0) + return -EBADMSG; + + switch (algo) { + case KMIP_CRYPTO_ALGO_RSA: + type = EVP_PKEY_RSA; + break; + case KMIP_CRYPTO_ALGO_DSA: + type = EVP_PKEY_DSA; + break; + case KMIP_CRYPTO_ALGO_ECDSA: + type = EVP_PKEY_EC; + break; + default: + return -EINVAL; + } + + *pub_key = d2i_PublicKey(type, NULL, &buf, len); + if (*pub_key == NULL) + return -EIO; + + return 0; +} + +/** + * Constructs a PKCS#8 Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Byte String v1.0 + * + * @param pub_key the public key as OpenSSL PKEY + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_pkcs8_public_key(EVP_PKEY *pub_key) +{ + struct kmip_node *ret = NULL; + unsigned char *buf = NULL; + int len; + + if (pub_key == NULL) + return NULL; + + len = i2d_PUBKEY(pub_key, &buf); + if (len <= 0) + return NULL; + + ret = kmip_node_new_byte_string(KMIP_TAG_KEY_MATERIAL, NULL, buf, len); + + OPENSSL_free(buf); + return ret; +} + +/** + * Gets the information from a PKCS#8 Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Byte String v1.0 + * + * @param node the KMIP node + * @param pub_key On return: the public key as OpenSSL PKEY. Must be + * freed by the caller using EVP_PKEY_free() when no + * longer needed. + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_pkcs8_public_key(const struct kmip_node *node, + EVP_PKEY **pub_key) +{ + const unsigned char *buf; + uint32_t len = 0; + + if (node == NULL || pub_key == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_MATERIAL) + return -EBADMSG; + + buf = kmip_node_get_byte_string(node, &len); + if (buf == NULL || len == 0) + return -EBADMSG; + + *pub_key = d2i_PUBKEY(NULL, &buf, len); + if (*pub_key == NULL) + return -EIO; + + return 0; +} + +/** + * Constructs a Raw Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Byte String v1.0 + * + * @param key the raw key + * @param key_len the length of the key + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_raw_key(const unsigned char *key, uint32_t key_len) +{ + + if (key == NULL) + return NULL; + + return kmip_node_new_byte_string(KMIP_TAG_KEY_MATERIAL, NULL, key, + key_len); +} + +/** + * Gets the information from a Raw Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Key Material Byte String v1.0 + * + * @param node the KMIP node + * @param key On return: the raw key + * @param key_len On return: the length of the key + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_raw_key(const struct kmip_node *node, const unsigned char **key, + uint32_t *key_len) +{ + if (node == NULL || key == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_KEY_MATERIAL) + return -EBADMSG; + + *key = kmip_node_get_byte_string(node, key_len); + if (*key == NULL) + return -EBADMSG; + + return 0; +} + + +/** + * Constructs a Symmetric Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Symmetric Key Structure v1.0 + * Key Block Yes Structure v1.0 + * + * @param keyblock the key block node + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_symmetric_key(struct kmip_node *keyblock) +{ + if (keyblock == NULL) + return NULL; + + return kmip_node_new_structure_va(KMIP_TAG_SYMMETRIC_KEY, NULL, 1, + keyblock); +} + +/** + * Gets the information from a Symmetric Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Symmetric Key Structure v1.0 + * Key Block Yes Structure v1.0 + * + * @param node the KMIP node + * @param keyblock On return: the key block node + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_symmetric_key(const struct kmip_node *node, + struct kmip_node **keyblock) +{ + if (node == NULL || keyblock == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_SYMMETRIC_KEY) + return -EBADMSG; + + *keyblock = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_BLOCK, + 0); + if (*keyblock == NULL) + return -EBADMSG; + + return 0; +} + +/** + * Constructs a Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Public Key Structure v1.0 + * Key Block Yes Structure v1.0 + * + * @param keyblock the key block node + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_public_key(struct kmip_node *keyblock) +{ + if (keyblock == NULL) + return NULL; + + return kmip_node_new_structure_va(KMIP_TAG_PUBLIC_KEY, NULL, 1, + keyblock); +} + +/** + * Gets the information from a Public Key node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Public Key Structure v1.0 + * Key Block Yes Structure v1.0 + * + * @param node the KMIP node + * @param keyblock On return: the key block node + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_public_key(const struct kmip_node *node, + struct kmip_node **keyblock) +{ + if (node == NULL || keyblock == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_PUBLIC_KEY) + return -EBADMSG; + + *keyblock = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_KEY_BLOCK, + 0); + if (*keyblock == NULL) + return -EBADMSG; + + return 0; +} + diff --git a/libkmipclient/kmip.c b/libkmipclient/kmip.c new file mode 100644 index 00000000..b313f1f8 --- /dev/null +++ b/libkmipclient/kmip.c @@ -0,0 +1,1595 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include +#include +#include +#include + +#include +#include + +#include "kmip.h" +#include "utils.h" + +void __attribute__ ((constructor)) kmip_init(void); +void __attribute__ ((destructor)) kmip_exit(void); + +/** + * Constructs a new KMIP node with the specified tag and type, and an optional + * name. The newly allocated node has a reference count of 1. + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param type the type of the new node + * + * @returns the allocated node, or NULL in case of an error + */ +static struct kmip_node *kmip_node_new(enum kmip_tag tag, const char *name, + enum kmip_type type) +{ + struct kmip_node *node; + + node = calloc(1, sizeof(struct kmip_node)); + if (node == NULL) + return NULL; + + node->ref_count = 1; + node->tag = tag; + node->type = type; + + if (name != NULL) { + node->name = strdup(name); + if (node->name == NULL) { + free(node); + return NULL; + } + } + + return node; +} + +/** + * Returns the tag of a KMIP node + * + * @param node the KMIP node + * + * @returns the tag + */ +enum kmip_tag kmip_node_get_tag(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + return node->tag; +} + +/** + * Returns the type of a KMIP node + * + * @param node the KMIP node + * + * @returns the type + */ +enum kmip_type kmip_node_get_type(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + return node->type; +} + +/** + * Returns the name of a KMIP node + * + * @param node the KMIP node + * + * @returns a copy of the name. The caller must free the returnd string. + */ +char *kmip_node_get_name(const struct kmip_node *node) +{ + if (node == NULL) + return NULL; + + if (node->name == NULL) + return NULL; + + return strdup(node->name); +} + +/** + * Constructs a new KMIP node of type structure with the specified tag, and an + * optional name, and the elements. The reference count of each added element is + * increased. + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param num_elements the number of elements to add + * @param elements the array elements to add. + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_structure(enum kmip_tag tag, const char *name, + unsigned int num_elements, + struct kmip_node **elements) +{ + struct kmip_node *node; + int rc; + + node = kmip_node_new(tag, name, KMIP_TYPE_STRUCTURE); + if (node == NULL) + return NULL; + + rc = kmip_node_add_structure_elements(node, num_elements, elements); + if (rc != 0) { + kmip_node_free(node); + return NULL; + } + + return node; +} + +/** + * Constructs a new KMIP node of type structure with the specified tag, and an + * optional name, and the elements. The reference count of each added element is + * increased. + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param num_elements the number of elements following as variable args + * @param the elements to add. Elements may be NULL, those + * are skipped + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_structure_va(enum kmip_tag tag, + const char *name, + unsigned int num_elements, ...) +{ + struct kmip_node *node, **elements = NULL; + unsigned int i; + va_list ap; + + if (num_elements > 0) { + elements = calloc(num_elements, sizeof(struct kmip_node *)); + if (elements == NULL) + return NULL; + } + + va_start(ap, num_elements); + for (i = 0; i < num_elements; i++) + elements[i] = va_arg(ap, struct kmip_node *); + va_end(ap); + + node = kmip_node_new_structure(tag, name, num_elements, elements); + + if (elements != NULL) + free(elements); + + return node; +} + +/** + * Add an element to a KMIP node (which must be of type KMIP_TYPE_STRUCTURE). + * The element is added as the last element. The reference count of the added + * element is increased. + * + * @param node the structure node to add the element to + * @param element the element to add + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_node_add_structure_element(struct kmip_node *node, + struct kmip_node *element) +{ + if (node == NULL || element == NULL) + return -EINVAL; + + return kmip_node_add_structure_elements(node, 1, &element); +} + +/** + * Add elements to a KMIP node (which must be of type KMIP_TYPE_STRUCTURE). + * The elements are added after the last element. The reference count of the + * added elements is increased. + * + * @param node the structure node to add the element to + * @param num_elements the number of elements to add + * @param elements the array elements to add + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_node_add_structure_elements(struct kmip_node *node, + unsigned int num_elements, + struct kmip_node **elements) +{ + struct kmip_node *element, *last; + unsigned int i; + + if (node == NULL || (num_elements > 0 && elements == NULL)) + return -EINVAL; + + if (node->type != KMIP_TYPE_STRUCTURE) + return -EINVAL; + + if (node->structure_value == NULL) { + last = NULL; + } else { + last = node->structure_value; + while (last->next != NULL) + last = last->next; + } + + for (i = 0; i < num_elements; i++) { + element = elements[i]; + if (element == NULL) + continue; + + kmip_node_upref(element); + + element->parent = node; + element->next = NULL; + + if (last == NULL) + node->structure_value = element; + else + last->next = element; + + last = element; + } + + return 0; +} + +/** + * Returns the number of elements of a KMIP node of type structure + * + * @param node the KMIP node + * + * @returns the number of elements, or -1 if the node is not of type structure + */ +unsigned int kmip_node_get_structure_element_count(const struct kmip_node *node) +{ + struct kmip_node *element; + unsigned int i; + + if (node == NULL) + return -1; + + if (node->type != KMIP_TYPE_STRUCTURE) + return -1; + + element = node->structure_value; + for (i = 0; element != NULL; i++) + element = element->next; + + return i; +} + +/** + * Returns an element of a KMIP node of type structure + * + * @param node the KMIP node + * @param index the index of the element to return + * + * @returns the element or NULL if no element is available at the specified + * index, or the node is not of type structure. + * The reference count of the returned element is increased. The caller must + * free the element via kmip_node_free() when no longer needed. + */ +struct kmip_node *kmip_node_get_structure_element_by_index( + const struct kmip_node *node, + unsigned int index) +{ + struct kmip_node *element; + unsigned int i; + + if (node == NULL) + return NULL; + + if (node->type != KMIP_TYPE_STRUCTURE) + return NULL; + + element = node->structure_value; + for (i = 0; i < index && element != NULL; i++) + element = element->next; + + if (element != NULL) + kmip_node_upref(element); + + return element; +} + +/** + * Returns the number of elements of a KMIP node of type structure of a + * certain tag + * + * @param node the KMIP node + * @param tag the tag to find + * + * @returns the number of elements, or -1 if the node is not of type structure + */ +unsigned int kmip_node_get_structure_element_by_tag_count( + const struct kmip_node *node, + enum kmip_tag tag) +{ + struct kmip_node *element; + unsigned int i; + + if (node == NULL) + return -1; + + if (node->type != KMIP_TYPE_STRUCTURE) + return -1; + + element = node->structure_value; + for (i = 0; element != NULL; element = element->next) { + if (element->tag != tag) + continue; + i++; + } + + return i; +} + +/** + * Find a structure element by its tag. If multiple elements with the matching + * tag are found, then the num'th one is returned. + * + * @param node the structure node to find the elements in + * @param tag the tag to find + * @param index the index of elements with the same tag to return. + * + * @returns the element node, or NULL if no element with the tag was found. + * The reference count of the returned element is increased. The caller must + * free the element via kmip_node_free() when no longer needed. + */ +struct kmip_node *kmip_node_get_structure_element_by_tag( + const struct kmip_node *node, + enum kmip_tag tag, unsigned int index) +{ + struct kmip_node *e; + + if (node == NULL) + return NULL; + + if (node->type != KMIP_TYPE_STRUCTURE) + return NULL; + + e = node->structure_value; + while (e != NULL) { + if (e->tag == tag) { + if (index == 0) { + kmip_node_upref(e); + return e; + } + index--; + } + e = e->next; + } + + return NULL; +} + +/** + * Constructs a new KMIP node of type integer with the specified tag, and an + * optional name, and the integer value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_integer(enum kmip_tag tag, const char *name, + int32_t value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_INTEGER); + if (node == NULL) + return NULL; + + node->integer_value = value; + node->length = sizeof(int32_t); + return node; +} + +/** + * Returns the value of a KMIP node of type integer + * + * @param node the KMIP node + * + * @returns the value of the node, or 0 if the node is not of type integer + */ +int32_t kmip_node_get_integer(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + if (node->type != KMIP_TYPE_INTEGER) + return 0; + + return node->integer_value; +} + +/** + * Constructs a new KMIP node of type long integer with the specified tag, and + * an optional name, and the long integer value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_long(enum kmip_tag tag, const char *name, + int64_t value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_LONG_INTEGER); + if (node == NULL) + return NULL; + + node->long_value = value; + node->length = sizeof(int64_t); + return node; +} + +/** + * Returns the value of a KMIP node of type long integer + * + * @param node the KMIP node + * + * @returns the value of the node, or 0 if the node is not of type long integer + */ +int64_t kmip_node_get_long(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + if (node->type != KMIP_TYPE_LONG_INTEGER) + return 0; + + return node->long_value; +} + +/** + * Constructs a new KMIP node of type big integer with the specified tag, and + * an optional name, and the big integer value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value as OpenSSL BIGNUM (can be NULL) + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_bigint(enum kmip_tag tag, const char *name, + const BIGNUM *value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_BIG_INTEGER); + if (node == NULL) + return NULL; + + if (value != NULL) { + node->big_integer_value = BN_dup(value); + node->length = kmip_encode_bignum_length(value); + } + return node; +} + +/** + * Returns the value of a KMIP node of type big integer + * + * @param node the KMIP node + * + * @returns the value of the node, or NULL if the node is not of type big + * integer, or no BIGNUM is set. The returned BIGNUM still belongs to the node, + * and must not be freed by the caller. It is freed together with the node it + * was obtained from. + */ +const BIGNUM *kmip_node_get_bigint(const struct kmip_node *node) +{ + if (node == NULL) + return NULL; + + if (node->type != KMIP_TYPE_BIG_INTEGER) + return NULL; + + return node->big_integer_value; +} + +/** + * Constructs a new KMIP node of type enumeration with the specified tag, and + * an optional name, and the enumeration value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param enumeration the enumeration value + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_enumeration(enum kmip_tag tag, const char *name, + uint32_t enumeration) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_ENUMERATION); + if (node == NULL) + return NULL; + + node->enumeration_value = enumeration; + node->length = sizeof(uint32_t); + return node; +} + +/** + * Returns the value of a KMIP node of type enumeration + * + * @param node the KMIP node + * + * @returns the value of the node, or 0 if the node is not of type enumeration + */ +uint32_t kmip_node_get_enumeration(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + if (node->type != KMIP_TYPE_ENUMERATION) + return 0; + + return node->enumeration_value; +} + +/** + * Constructs a new KMIP node of type boolean with the specified tag, and + * an optional name, and the boolean value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_boolean(enum kmip_tag tag, const char *name, + bool value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_BOOLEAN); + if (node == NULL) + return NULL; + + node->boolean_value = value; + node->length = sizeof(uint64_t); + return node; +} + +/** + * Returns the value of a KMIP node of type boolean + * + * @param node the KMIP node + * + * @returns the value of the node, or 0 if the node is not of type boolean + */ +bool kmip_node_get_boolean(const struct kmip_node *node) +{ + if (node == NULL) + return false; + + if (node->type != KMIP_TYPE_BOOLEAN) + return false; + + return node->boolean_value; +} + +/** + * Constructs a new KMIP node of type text string with the specified tag, and + * an optional name, and the text string value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value (can be NULL) + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_text_string(enum kmip_tag tag, const char *name, + const char *value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_TEXT_STRING); + if (node == NULL) + return NULL; + + if (value != NULL) { + node->text_value = strdup(value); + if (node->text_value == NULL) { + free(node); + return NULL; + } + node->length = strlen(value); + } + return node; +} + +/** + * Returns the value of a KMIP node of type text string + * + * @param node the KMIP node + * + * @returns the value of the node, or NULL if the node is not of type text + * string or no string is set. The returned string still belongs to the node, + * and must not be freed by the caller. It is freed together with the node it + * was obtained from. + */ +const char *kmip_node_get_text_string(const struct kmip_node *node) +{ + if (node == NULL) + return NULL; + + if (node->type != KMIP_TYPE_TEXT_STRING) + return NULL; + + return node->text_value; +} + +/** + * Constructs a new KMIP node of type byte string with the specified tag, and + * an optional name, and the byte string value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the byte string (can be NULL) + * @param length the length of the byte string + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_byte_string(enum kmip_tag tag, const char *name, + const unsigned char *value, + uint32_t length) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_BYTE_STRING); + if (node == NULL) + return NULL; + + if (value != NULL && length > 0) { + node->bytes_value = malloc(length); + if (node->bytes_value == NULL) { + free(node); + return NULL; + } + memcpy(node->bytes_value, value, length); + node->length = length; + } + return node; +} + +/** + * Returns the value of a KMIP node of type byte string + * + * @param node the KMIP node + * @param length On return, the length of the byte string + * + * @returns the value of the node, or NULL if the node is not of type byte + * string or no string is set. The returned string still belongs to the node, + * and must not be freed by the caller. It is freed together with the node it + * was obtained from. + */ +const unsigned char *kmip_node_get_byte_string(const struct kmip_node *node, + uint32_t *length) +{ + if (node == NULL) + return NULL; + + if (node->type != KMIP_TYPE_BYTE_STRING) + return NULL; + + if (length != NULL) + *length = node->length; + return node->bytes_value; +} + +/** + * Constructs a new KMIP node of type date and time with the specified tag, and + * an optional name, and the date and time value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_date_time(enum kmip_tag tag, const char *name, + int64_t value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_DATE_TIME); + if (node == NULL) + return NULL; + + node->date_time_value = value; + node->length = sizeof(int64_t); + return node; +} + +/** + * Returns the value of a KMIP node of type date and time + * + * @param node the KMIP node + * + * @returns the value of the node, or 0 if the node is not of type date and time + */ +int64_t kmip_node_get_date_time(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + if (node->type != KMIP_TYPE_DATE_TIME) + return 0; + + return node->date_time_value; +} + +/** + * Constructs a new KMIP node of type interval with the specified tag, and + * an optional name, and the interval value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_interval(enum kmip_tag tag, const char *name, + uint32_t value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_INTERVAL); + if (node == NULL) + return NULL; + + node->interval_value = value; + node->length = sizeof(uint32_t); + return node; +} + +/** + * Returns the value of a KMIP node of type interval + * + * @param node the KMIP node + * + * @returns the value of the node, or 0 if the node is not of type interval + */ +uint32_t kmip_node_get_interval(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + if (node->type != KMIP_TYPE_INTERVAL) + return 0; + + return node->interval_value; +} + +/** + * Constructs a new KMIP node of type date and time extended with the specified + * tag, and an optional name, and the date and time value + * + * @param tag the tag of the new node + * @param name Optional: the name of the node (only used with JSON + * or XML encoding). Can be NULL. + * @param value the value + * + * @returns the allocated node, or NULL in case of an error + */ +struct kmip_node *kmip_node_new_date_time_ext(enum kmip_tag tag, + const char *name, + int64_t value) +{ + struct kmip_node *node; + + node = kmip_node_new(tag, name, KMIP_TYPE_DATE_TIME_EXTENDED); + if (node == NULL) + return NULL; + + node->date_time_ext_value = value; + node->length = sizeof(int64_t); + return node; +} + +/** + * Returns the value of a KMIP node of type date and time extended + * + * @param node the KMIP node + * + * @returns the value of the node, or 0 if the node is not of type date and time + * extended + */ +int64_t kmip_node_get_date_time_ext(const struct kmip_node *node) +{ + if (node == NULL) + return 0; + + if (node->type != KMIP_TYPE_DATE_TIME_EXTENDED) + return 0; + + return node->date_time_ext_value; +} + +/** + * Clones (copies) a KMIP node with all its data and elements (in case of a + * structure node). + * + * @param node the KMIP node to clone + * + * @returns the cloned node, or NULL in case of an error + */ +struct kmip_node *kmip_node_clone(const struct kmip_node *node) +{ + struct kmip_node *clone, *element, *cloned_element; + int rc; + + clone = kmip_node_new(node->tag, node->name, node->type); + if (clone == NULL) + return NULL; + + switch (clone->type) { + case KMIP_TYPE_STRUCTURE: + element = node->structure_value; + while (element != NULL) { + cloned_element = kmip_node_clone(element); + if (cloned_element == NULL) + goto error; + rc = kmip_node_add_structure_element(clone, + cloned_element); + kmip_node_free(cloned_element); + if (rc != 0) + goto error; + element = element->next; + } + break; + case KMIP_TYPE_INTEGER: + clone->integer_value = node->integer_value; + break; + case KMIP_TYPE_LONG_INTEGER: + clone->long_value = node->long_value; + break; + case KMIP_TYPE_BIG_INTEGER: + clone->big_integer_value = BN_dup(node->big_integer_value); + if (clone->big_integer_value == NULL) + goto error; + break; + case KMIP_TYPE_ENUMERATION: + clone->enumeration_value = node->enumeration_value; + break; + case KMIP_TYPE_BOOLEAN: + clone->boolean_value = node->boolean_value; + break; + case KMIP_TYPE_TEXT_STRING: + if (node->text_value != NULL) { + clone->text_value = strdup(node->text_value); + if (node->text_value == NULL) + goto error; + clone->length = strlen(clone->text_value); + } + break; + case KMIP_TYPE_BYTE_STRING: + if (node->bytes_value != NULL && node->length > 0) { + clone->bytes_value = malloc(node->length); + if (clone->bytes_value == NULL) + goto error; + memcpy(clone->bytes_value, node->bytes_value, + node->length); + clone->length = node->length; + } + break; + case KMIP_TYPE_DATE_TIME: + clone->date_time_value = node->date_time_value; + break; + case KMIP_TYPE_INTERVAL: + clone->interval_value = node->interval_value; + break; + case KMIP_TYPE_DATE_TIME_EXTENDED: + clone->date_time_ext_value = node->date_time_ext_value; + break; + default: + goto error; + } + + return clone; + +error: + kmip_node_free(clone); + return NULL; +} + +/** + * Increments the reference count of a KMIP node + * + * @param node the node to increase the reference count for + */ +void kmip_node_upref(struct kmip_node *node) +{ + if (node == NULL) + return; + + __sync_add_and_fetch((unsigned long *)&node->ref_count, 1); +} + +/** + * Free a KMIP node, including its value (structure elements, etc) + * + * @param node the node to free + */ +void kmip_node_free(struct kmip_node *node) +{ + struct kmip_node *element, *next; + unsigned long ref_count = 0; + + if (node == NULL) + return; + + if (node->ref_count > 0) + ref_count = __sync_sub_and_fetch( + (unsigned long *)&node->ref_count, 1); + if (ref_count > 0) + return; + + switch (node->type) { + case KMIP_TYPE_STRUCTURE: + element = node->structure_value; + while (element != NULL) { + next = element->next; + + /* + * Unchain the element from the parent and next element, + * even if the element itself might not be freed (due + * to reference count). But the parent is freed, and + * thus the chain of elements is not longer existent. + */ + element->parent = NULL; + element->next = NULL; + + kmip_node_free(element); + + element = next; + } + break; + case KMIP_TYPE_BIG_INTEGER: + BN_free(node->big_integer_value); + break; + case KMIP_TYPE_TEXT_STRING: + free(node->text_value); + break; + case KMIP_TYPE_BYTE_STRING: + free(node->bytes_value); + break; + default: + break; + } + + free(node->name); + free(node); +} + +static struct kmip_version default_protocol_version = { + .major = KMIP_DEFAULT_PROTOCOL_VERSION_MAJOR, + .minor = KMIP_DEFAULT_PROTOCOL_VERSION_MINOR +}; + +/** + * Sets the default KMIP protocol version + * + * @param version the version to set + */ +void kmip_set_default_protocol_version(const struct kmip_version *version) +{ + if (version == NULL) + return; + + default_protocol_version.major = version->major; + default_protocol_version.minor = version->minor; +} + +/** + * Sets the default KMIP protocol version + * + * @returns the default KMIP protocol version + */ +const struct kmip_version *kmip_get_default_protocol_version(void) +{ + return &default_protocol_version; +} + +/** + * Constructs a new connection to a KMIP server using the specified connection + * configuration. The strings specified in the configuration are copied into the + * newly allocated connection, they can be freed by the caller after the new + * connection has been allocated. The reference count in the PKEY specified + * in the configuration is increased. The caller can free its PKEY as needed. + * + * @param config the connection configuration + * @param connection On return: a newly allocated KMIP connection + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_connection_new(const struct kmip_conn_config *config, + struct kmip_connection **connection, + bool debug) +{ + struct kmip_connection *conn = NULL; + int rc; + + if (config == NULL || connection == NULL) + return -EINVAL; + + *connection = NULL; + + switch (config->encoding) { + case KMIP_ENCODING_TTLV: + /* TTLV can be used with both, plain-TLS and HTTPS */ + switch (config->transport) { + case KMIP_TRANSPORT_PLAIN_TLS: + case KMIP_TRANSPORT_HTTPS: + break; + default: + kmip_debug(debug, "Invalid transport: %d", + config->transport); + return -EINVAL; + } + break; + case KMIP_ENCODING_JSON: + case KMIP_ENCODING_XML: + /* JSON(XML can only be used with HTTPS */ + switch (config->transport) { + case KMIP_TRANSPORT_PLAIN_TLS: + kmip_debug(debug, "JSON/XML encode can only be used " + "with HTTPS transport"); + return -EINVAL; + case KMIP_TRANSPORT_HTTPS: + break; + default: + kmip_debug(debug, "Invalid transport: %d", + config->transport); + return -EINVAL; + } + break; + + break; + default: + kmip_debug(debug, "Invalid encoding: %d", config->encoding); + return -EINVAL; + } + + if (config->server == NULL) { + kmip_debug(debug, "KMIP Server must be specified"); + return -EINVAL; + } + if (config->tls_client_key == NULL) { + kmip_debug(debug, "Client key must be specified"); + return -EINVAL; + } + if (config->tls_client_cert == NULL) { + kmip_debug(debug, "Client certificate must be specified"); + return -EINVAL; + } + + conn = calloc(1, sizeof(struct kmip_connection)); + if (conn == NULL) { + kmip_debug(debug, "calloc failed"); + return -ENOMEM; + } + + conn->config.encoding = config->encoding; + conn->config.transport = config->transport; + kmip_debug(debug, "encoding: %d", conn->config.encoding); + kmip_debug(debug, "transport: %d", conn->config.transport); + + conn->config.server = strdup(config->server); + if (conn->config.server == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "server: '%s'", conn->config.server); + + conn->config.tls_client_key = config->tls_client_key; + if (EVP_PKEY_up_ref(conn->config.tls_client_key) != 1) { + kmip_debug(debug, "EVP_PKEY_up_ref failed"); + rc = -EIO; + goto out; + } + kmip_debug(debug, "client key: %p", conn->config.tls_client_key); + + conn->config.tls_client_cert = strdup(config->tls_client_cert); + if (conn->config.tls_client_cert == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "client cert: '%s'", conn->config.tls_client_cert); + + if (config->tls_ca != NULL) { + conn->config.tls_ca = strdup(config->tls_ca); + if (conn->config.tls_ca == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "CA: '%s'", conn->config.tls_ca); + } + + if (config->tls_issuer_cert != NULL) { + conn->config.tls_issuer_cert = strdup(config->tls_issuer_cert); + if (conn->config.tls_issuer_cert == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "issuer cert: '%s'", + conn->config.tls_issuer_cert); + } + + if (config->tls_pinned_pubkey != NULL) { + conn->config.tls_pinned_pubkey = + strdup(config->tls_pinned_pubkey); + if (conn->config.tls_pinned_pubkey == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "pinned pubkey: '%s'", + conn->config.tls_pinned_pubkey); + } + + if (config->tls_server_cert != NULL) { + conn->config.tls_server_cert = strdup(config->tls_server_cert); + if (conn->config.tls_server_cert == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "server cert: '%s'", + conn->config.tls_server_cert); + } + + conn->config.tls_verify_peer = config->tls_verify_peer; + conn->config.tls_verify_host = config->tls_verify_host; + kmip_debug(debug, "verify peer: %d", conn->config.tls_verify_peer); + kmip_debug(debug, "verify host: %d", conn->config.tls_verify_host); + + if (config->tls_cipher_list != NULL) { + conn->config.tls_cipher_list = strdup(config->tls_cipher_list); + if (conn->config.tls_cipher_list == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "TLS cipher list: '%s'", + conn->config.tls_cipher_list); + } + + if (config->tls13_cipher_list != NULL) { + conn->config.tls13_cipher_list = + strdup(config->tls13_cipher_list); + if (conn->config.tls13_cipher_list == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + kmip_debug(debug, "TLSv1.3 cipher list: '%s'", + conn->config.tls13_cipher_list); + } + + switch (conn->config.transport) { + case KMIP_TRANSPORT_PLAIN_TLS: + rc = kmip_connection_tls_init(conn, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_connection_tls_init failed"); + goto out; + } + break; + case KMIP_TRANSPORT_HTTPS: + rc = kmip_connection_https_init(conn, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_connection_https_init failed"); + goto out; + } + break; + default: + kmip_debug(debug, "Invalid transport: %d", + conn->config.transport); + rc = -EINVAL; + goto out; + } + + *connection = conn; + rc = 0; + +out: + if (rc != 0) + kmip_connection_free(conn); + + return rc; +} + +/** + * Perform a request over the KMIP connection + * + * @param connection the KMIP connection + * @param request the request to send + * @param response On return: the received response. Must be freed by + * the caller. + * + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_connection_perform(struct kmip_connection *connection, + struct kmip_node *request, + struct kmip_node **response, + bool debug) +{ + int rc; + + if (connection == NULL || request == NULL || response == NULL) + return -EINVAL; + + kmip_debug(debug, "KMIP Request:"); + kmip_node_dump(request, debug); + + switch (connection->config.transport) { + case KMIP_TRANSPORT_PLAIN_TLS: + rc = kmip_connection_tls_perform(connection, request, + response, debug); + break; + case KMIP_TRANSPORT_HTTPS: + rc = kmip_connection_https_perform(connection, request, + response, debug); + break; + default: + return -EINVAL; + } + + if (rc == 0 && *response != NULL) { + kmip_debug(debug, "KMIP Response:"); + kmip_node_dump(*response, debug); + } + + return rc; +} + +/** + * Terminates and frees a KMIP connection. + * + * @param connection the KMIP connection to free + */ +void kmip_connection_free(struct kmip_connection *connection) +{ + if (connection == NULL) + return; + + switch (connection->config.transport) { + case KMIP_TRANSPORT_PLAIN_TLS: + kmip_connection_tls_term(connection); + break; + case KMIP_TRANSPORT_HTTPS: + kmip_connection_https_term(connection); + break; + default: + break; + } + + free((void *)connection->config.server); + EVP_PKEY_free(connection->config.tls_client_key); + free((void *)connection->config.tls_client_cert); + if (connection->config.tls_ca != NULL) + free((void *)connection->config.tls_ca); + if (connection->config.tls_issuer_cert != NULL) + free((void *)connection->config.tls_issuer_cert); + if (connection->config.tls_pinned_pubkey != NULL) + free((void *)connection->config.tls_pinned_pubkey); + if (connection->config.tls_server_cert != NULL) + free((void *)connection->config.tls_server_cert); + if (connection->config.tls_cipher_list != NULL) + free((void *)connection->config.tls_cipher_list); + if (connection->config.tls13_cipher_list != NULL) + free((void *)connection->config.tls13_cipher_list); + + free(connection); +} + +/** + * Retrieves the serevr's certificate, public key and certificate chain + * + * @param server the KMIP server. + * For Plain-TLS transport, only the hostname and + * optional port number. + * For HTTPS transport, an URL in the form + * 'https://hostname[:port]/uri' + * @param transport the transport mode + * @param ca Optional: File name of the CA bundle PEM file, or a + * name of a directory the multiple CA certificates. + * If this is NULL, then the default system path for + * CA certificates is used. + * @param client_key the client key as an OpenSSL PKEY object. + * @param client_cert File name of the client certificate PEM file + * @param server_cert_pem File name of a PEM file into which the server + * certificate is written. If NULL then ignored. + * @param server_pubkey_pem File name of a PEM file into which the server + * public key is written. If NULL then ignored. + * @param cert_chain_pem File name of a PEM file into which the certificate + * chain (excluding the server certificate) is written. + * If NULL then ignored. + * @param verified On return: If the server 's certificate has been + * verified using the CA specification (if ca = NULL: + * default system CAs, otherwise path or file to CAs). + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_connection_get_server_cert(const char *server, + enum kmip_transport transport, + const char *ca, + EVP_PKEY *client_key, + const char *client_cert, + const char *server_cert_pem, + const char *server_pubkey_pem, + const char *cert_chain_pem, + bool *verified, + bool debug) +{ + struct kmip_conn_config config = { 0 }; + struct kmip_connection *conn = NULL; + int rc, numcerts, i, port_found = 0; + char *hostname = NULL, *tok, *tok2; + STACK_OF(X509) *chain; + bool do_verify = true; + FILE *fp = NULL; + X509 *cert; + + if (server == NULL || client_key == NULL || client_cert == NULL) + return -EINVAL; + + config.encoding = KMIP_ENCODING_TTLV; + config.transport = KMIP_TRANSPORT_PLAIN_TLS; + config.tls_ca = ca; + config.tls_client_key = client_key; + config.tls_client_cert = client_cert; + config.tls_verify_host = false; + config.tls_verify_peer = false; + config.tls_cipher_list = NULL; + config.tls13_cipher_list = NULL; + + if (transport == KMIP_TRANSPORT_HTTPS) { + if (strncmp(server, "https://", 8) != 0) { + kmip_debug(debug, "Server must start with 'https://'"); + return -EINVAL; + } + server += 8; + + /* Find port (if any) and beginning of uri */ + if (*server == '[') { + /* IPv6 address enclosed in square brackets */ + tok = strchr(server, ']'); + if (tok == NULL) { + kmip_debug(debug, "malformed IPv6 address"); + return -EINVAL; + } + tok++; + if (*tok == ':') { + port_found = 1; + tok2 = strchr(tok, '/'); + if (tok2 == NULL) + tok2 = tok + strlen(tok); + } else { + tok2 = strchr(tok, '/'); + if (tok2 == NULL) + tok2 = tok + strlen(tok); + } + } else { + /* hostname or IPv4 address */ + tok = strchr(server, ':'); + if (tok != NULL) { + port_found = 1; + tok2 = strchr(tok, '/'); + if (tok2 == NULL) + tok2 = tok + strlen(tok); + } else { + tok2 = strchr(server, '/'); + if (tok2 == NULL) + tok2 = (char *)server + strlen(server); + } + } + + hostname = calloc(1, tok2 - server + (!port_found ? 5 : 1)); + if (hostname == NULL) { + kmip_debug(debug, "calloc failed"); + return -ENOMEM; + } + strncpy(hostname, server, tok2 - server); + if (!port_found) { + strcat(hostname, ":"); + strcat(hostname, KMIP_DEFAULT_HTTPS_PORT); + } + + config.server = hostname; + } else { + config.server = server; + } + +retry: + config.tls_verify_peer = do_verify; + rc = kmip_connection_new(&config, &conn, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_connection_new failed (do_verify: %d)", + do_verify); + + if (do_verify) { + /* + * If peer verification failed (e.g. due to a self + * signed server certificate), try again without peer + * verification. + */ + do_verify = false; + goto retry; + } + goto out; + } + + if (verified != NULL) + *verified = do_verify; + + chain = SSL_get_peer_cert_chain(conn->plain_tls.ssl); + if (chain == NULL) { + kmip_debug(debug, "SSL_get_peer_cert_chain failed"); + return -EIO; + goto out; + } + + numcerts = sk_X509_num(chain); + for (i = 0; i < numcerts; i++) { + cert = sk_X509_value(chain, i); + if (cert == NULL) + break; + + if (debug) { + kmip_debug(debug, "%d. Certificate:", i); + X509_print_ex_fp(stderr, cert, XN_FLAG_COMPAT, + X509_FLAG_COMPAT); + } + + if (i == 0 && server_cert_pem != NULL) { + fp = fopen(server_cert_pem, "w"); + if (fp == NULL) { + rc = -errno; + kmip_debug(debug, "Failed to open %s for write", + server_cert_pem, strerror(-rc)); + goto out; + } + + if (PEM_write_X509(fp, cert) != 1) { + kmip_debug(debug, "PEM_write_X509 failed to " + "write to %s", server_cert_pem); + rc = -EIO; + goto out; + } + fclose(fp); + fp = NULL; + + if (server_pubkey_pem != NULL) { + fp = fopen(server_pubkey_pem, "w"); + if (fp == NULL) { + rc = -errno; + kmip_debug(debug, "Failed to open %s " + "for write", + server_pubkey_pem, + strerror(-rc)); + goto out; + } + + if (PEM_write_PUBKEY(fp, X509_get0_pubkey(cert)) + != 1) { + kmip_debug(debug, "PEM_write_PUBKEY " + "failed to write to %s", + server_pubkey_pem); + rc = -EIO; + goto out; + } + fclose(fp); + fp = NULL; + } + continue; + } + + if (i > 0 && cert_chain_pem != NULL) { + if (fp == NULL) + fp = fopen(cert_chain_pem, "w"); + if (fp == NULL) { + rc = -errno; + kmip_debug(debug, "Failed to open %s for write", + cert_chain_pem, strerror(-rc)); + goto out; + } + + if (PEM_write_X509(fp, cert) != 1) { + kmip_debug(debug, "PEM_write_X509 failed to " + "write to %s", cert_chain_pem); + rc = -EIO; + goto out; + } + } + } + + rc = 0; + +out: + if (fp != NULL) + fclose(fp); + if (conn != NULL) + kmip_connection_free(conn); + if (hostname != NULL) + free(hostname); + + return rc; +} + +/** + * Library constructor + */ +void __attribute__ ((constructor)) kmip_init(void) +{ + CURLsslset rc; + + /* + * Ensure that curl uses OpenSSL as SSL backend. If curl has already + * been itialized by the calling application, the backend can't be + * changed anymore, but we continue anyway. However, it will later be + * checked if curl uses the OpenSSL backend, and a HTTPS connection + * will fail if it is not using the OpenSSL backend. + */ + rc = curl_global_sslset(CURLSSLBACKEND_OPENSSL, NULL, NULL); + if (rc != CURLSSLSET_OK && rc != CURLSSLSET_TOO_LATE) + errx(EXIT_FAILURE, "libkmipclient: libcurl was not built with " + "the OpenSSL backend"); + + curl_global_init(CURL_GLOBAL_ALL); +} + +/** + * Library destructor + */ +void __attribute__ ((destructor)) kmip_exit(void) +{ + curl_global_cleanup(); +} diff --git a/libkmipclient/kmip.h b/libkmipclient/kmip.h new file mode 100644 index 00000000..e9185776 --- /dev/null +++ b/libkmipclient/kmip.h @@ -0,0 +1,111 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ +#ifndef KMIP_H +#define KMIP_H + +#include +#include + +#include +#include + +#include +#include +#include + +#include "kmipclient/kmipclient.h" + +/* KMIP Connection related structures */ +#define KMIP_DEFAULT_PROTOCOL_VERSION_MAJOR 1 +#define KMIP_DEFAULT_PROTOCOL_VERSION_MINOR 0 + +struct kmip_connection { + struct kmip_conn_config config; + union { + struct { + SSL_CTX *ssl_ctx; + SSL *ssl; + BIO *bio; + } plain_tls; + struct { + CURL **curl; + struct curl_slist *headers; + } https; + }; +}; + +/* KMIP node related structures */ +struct kmip_node { + enum kmip_tag tag; + enum kmip_type type; + unsigned int length; + char *name; /* optional, only used for JSON and XML encoding */ + union { + struct kmip_node *structure_value; + int32_t integer_value; + int64_t long_value; + BIGNUM *big_integer_value; + uint32_t enumeration_value; + bool boolean_value; + char *text_value; + unsigned char *bytes_value; + int64_t date_time_value; + uint32_t interval_value; + int64_t date_time_ext_value; + }; + struct kmip_node *parent; + struct kmip_node *next; + volatile unsigned long ref_count; +}; + +/* Attribute related internal functions */ +int kmip_v2_attr_from_v1_attr(struct kmip_node *v1_attr, + struct kmip_node **v2_attr); +int kmip_v1_attr_from_v2_attr(struct kmip_node *v2_attr, + struct kmip_node **v1_attr); + +char *kmip_build_v1_custom_attr_name(const char *vendor_id, + const char *attr_name); + +struct kmip_node *kmip_new_attribute_name_v1( + const struct kmip_node *v2_attr_ref); +int kmip_get_attribute_name_v1(const struct kmip_node *node, + struct kmip_node **v2_attr_ref); + +/* Connection related internal functions */ +int kmip_connection_tls_init(struct kmip_connection *connection, bool debug); +int kmip_connection_tls_perform(struct kmip_connection *connection, + struct kmip_node *request, + struct kmip_node **response, + bool debug); +void kmip_connection_tls_term(struct kmip_connection *connection); + +int kmip_connection_https_init(struct kmip_connection *connection, bool debug); +int kmip_connection_https_perform(struct kmip_connection *connection, + struct kmip_node *request, + struct kmip_node **response, + bool debug); +void kmip_connection_https_term(struct kmip_connection *connection); + +/* KIMP decoding and encoding internal functions */ +int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node, + bool debug); +int kmip_encode_ttlv(struct kmip_node *node, BIO *bio, size_t *size, + bool debug); + +int kmip_decode_json(const json_object *obj, struct kmip_node *parent, + struct kmip_node **node, bool debug); +int kmip_encode_json(const struct kmip_node *node, json_object **obj, + bool debug); + +int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent, + struct kmip_node **node, bool debug); +int kmip_encode_xml(const struct kmip_node *node, xmlNode **xml, bool debug); + +#endif diff --git a/libkmipclient/libkmipclient.map b/libkmipclient/libkmipclient.map new file mode 100644 index 00000000..f949d1cd --- /dev/null +++ b/libkmipclient/libkmipclient.map @@ -0,0 +1,225 @@ +LIBKMIPCLIENT_1.0 { + global: + kmip_node_clone; + kmip_node_upref; + kmip_node_free; + kmip_node_get_tag; + kmip_node_get_type; + kmip_node_get_name; + kmip_node_dump; + kmip_node_new_structure; + kmip_node_new_structure_va; + kmip_node_get_structure_element_count; + kmip_node_get_structure_element_by_index; + kmip_node_get_structure_element_by_tag_count; + kmip_node_get_structure_element_by_tag; + kmip_node_add_structure_element; + kmip_node_add_structure_elements; + kmip_node_new_integer; + kmip_node_get_integer; + kmip_node_new_long; + kmip_node_get_long; + kmip_node_new_bigint; + kmip_node_get_bigint; + kmip_node_new_enumeration; + kmip_node_get_enumeration; + kmip_node_new_boolean; + kmip_node_get_boolean; + kmip_node_new_text_string; + kmip_node_get_text_string; + kmip_node_new_byte_string; + kmip_node_get_byte_string; + kmip_node_new_date_time; + kmip_node_get_date_time; + kmip_node_new_interval; + kmip_node_get_interval; + kmip_node_new_date_time_ext; + kmip_node_get_date_time_ext; + kmip_set_default_protocol_version; + kmip_get_default_protocol_version; + kmip_new_protocol_version; + kmip_new_profile_version; + kmip_new_request_header; + kmip_new_request_batch_item; + kmip_new_request; + kmip_new_request_va; + kmip_new_query_request_payload; + kmip_new_query_request_payload_va; + kmip_new_discover_versions_payload; + kmip_new_discover_versions_payload_va; + kmip_new_protection_storage_masks; + kmip_new_protection_storage_masks_va; + kmip_new_create_request_payload; + kmip_new_create_request_payload_va; + kmip_new_get_attribute_list_request_payload; + kmip_new_get_attributes_request_payload; + kmip_new_get_attributes_request_payload_va; + kmip_new_add_attribute_request_payload; + kmip_new_modify_attribute_request_payload; + kmip_new_set_attribute_v2_request_payload; + kmip_new_delete_attribute_request_payload; + kmip_new_activate_request_payload; + kmip_new_destroy_request_payload; + kmip_new_archive_request_payload; + kmip_new_recover_request_payload; + kmip_new_revoke_request_payload; + kmip_new_locate_request_payload; + kmip_new_locate_request_payload_va; + kmip_new_register_request_payload; + kmip_new_register_request_payload_va; + kmip_new_get_request_payload; + kmip_get_protocol_version; + kmip_get_profile_version; + kmip_get_response_header; + kmip_get_response_batch_item; + kmip_get_response; + kmip_get_query_response_payload; + kmip_get_discover_versions_response_payload; + kmip_get_create_response_payload; + kmip_get_get_attribute_list_response_payload; + kmip_get_get_attributes_response_payload; + kmip_get_add_attribute_response_payload; + kmip_get_modify_attribute_response_payload; + kmip_get_set_attribute_v2_response_payload; + kmip_get_delete_attribute_response_payload; + kmip_get_activate_response_payload; + kmip_get_destroy_response_payload; + kmip_get_archive_response_payload; + kmip_get_recover_response_payload; + kmip_get_revoke_response_payload; + kmip_get_activate_response_payload; + kmip_get_locate_response_payload; + kmip_get_register_response_payload; + kmip_get_get_response_payload; + kmip_new_attributes; + kmip_new_attributes_va; + kmip_get_attributes; + kmip_new_vendor_attribute; + kmip_get_vendor_attribute; + kmip_new_attribute_reference; + kmip_get_attribute_reference; + kmip_new_current_new_attribute; + kmip_new_unique_identifier; + kmip_get_unique_identifier; + kmip_new_name; + kmip_get_name; + kmip_new_alternative_name; + kmip_get_alternative_name; + kmip_new_object_type; + kmip_get_object_type; + kmip_new_cryptographic_algorithm; + kmip_get_cryptographic_algorithm; + kmip_new_cryptographic_length; + kmip_get_cryptographic_length; + kmip_new_certificate_type; + kmip_get_certificate_type; + kmip_new_cryptographic_usage_mask; + kmip_get_cryptographic_usage_mask; + kmip_new_state; + kmip_get_state; + kmip_new_initial_date; + kmip_get_initial_date; + kmip_new_activation_date; + kmip_get_activation_date; + kmip_new_deactivation_date; + kmip_get_deactivation_date; + kmip_new_destroy_date; + kmip_get_destroy_date; + kmip_new_compromise_date; + kmip_get_compromise_date; + kmip_new_compromise_occurrence_date; + kmip_get_compromise_occurrence_date; + kmip_new_last_change_date; + kmip_get_last_change_date; + kmip_new_original_creation_date; + kmip_get_original_creation_date; + kmip_new_archive_date; + kmip_get_archive_date; + kmip_new_process_start_date; + kmip_get_process_start_date; + kmip_new_protect_stop_date; + kmip_get_protect_stop_date; + kmip_new_cryptographic_parameters; + kmip_get_cryptographic_parameter; + kmip_new_cryptographic_domain_parameters; + kmip_get_cryptographic_domain_parameters; + kmip_new_digital_signature_algorithm; + kmip_get_digital_signature_algorithm; + kmip_new_object_group; + kmip_get_object_group; + kmip_new_revocation_reason; + kmip_get_revocation_reason; + kmip_new_contact_information; + kmip_get_contact_information; + kmip_new_description; + kmip_get_description; + kmip_new_comment; + kmip_get_comment; + kmip_new_key_format_type; + kmip_get_key_format_type; + kmip_new_protection_level; + kmip_get_protection_level; + kmip_new_protection_period; + kmip_get_protection_period; + kmip_new_protection_storage_mask; + kmip_get_protection_storage_mask; + kmip_new_fresh; + kmip_get_fresh; + kmip_new_key_value_present; + kmip_get_key_value_present; + kmip_new_short_unique_identifier; + kmip_get_short_unique_identifier; + kmip_new_application_specific_information; + kmip_get_application_specific_information; + kmip_new_key_value_location; + kmip_get_key_value_location; + kmip_new_digest; + kmip_get_digest; + kmip_new_sensitive; + kmip_get_sensitive; + kmip_new_always_sensitive; + kmip_get_always_sensitive; + kmip_new_extractable; + kmip_get_extractable; + kmip_new_never_extractable; + kmip_get_never_extractable; + kmip_new_link; + kmip_get_link; + kmip_new_linked_object_identifier; + kmip_get_linked_object_identifier; + kmip_new_operation_policy_name; + kmip_get_operation_policy_name; + kmip_new_lease_time; + kmip_get_lease_time; + kmip_new_key_block; + kmip_get_key_block; + kmip_new_key_value; + kmip_new_key_value_va; + kmip_get_key_value; + kmip_new_key_wrapping_data; + kmip_get_key_wrapping_data; + kmip_new_key_wrapping_specification; + kmip_new_key_wrapping_specification_va; + kmip_get_key_wrapping_specification; + kmip_new_key_info; + kmip_get_key_info; + kmip_new_transparent_symmetric_key; + kmip_get_transparent_symmetric_key; + kmip_new_transparent_rsa_public_key; + kmip_get_transparent_rsa_public_key; + kmip_new_pkcs1_public_key; + kmip_get_pkcs1_public_key; + kmip_new_pkcs8_public_key; + kmip_get_pkcs8_public_key; + kmip_new_raw_key; + kmip_get_raw_key; + kmip_new_symmetric_key; + kmip_get_symmetric_key; + kmip_new_public_key; + kmip_get_public_key; + kmip_connection_new; + kmip_connection_perform; + kmip_connection_free; + kmip_connection_get_server_cert; + local: *; +}; \ No newline at end of file diff --git a/libkmipclient/names.c b/libkmipclient/names.c new file mode 100644 index 00000000..fe005322 --- /dev/null +++ b/libkmipclient/names.c @@ -0,0 +1,2253 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include +#include + +#include "names.h" +#include "utils.h" + +static const struct kmip_enum kmip_tags[] = { + { .val = KMIP_TAG_ACTIVATION_DATE, .name = "ActivationDate" }, + { .val = KMIP_TAG_APPLICATION_DATA, .name = "ApplicationData" }, + { .val = KMIP_TAG_APPLICATION_NAMESPACE, + .name = "ApplicationNamespace" }, + { .val = KMIP_TAG_APPLICATION_SPECIFIC_INFORMATION, + .name = "ApplicationSpecificInformation" }, + { .val = KMIP_TAG_ARCHIVE_DATE, .name = "ArchiveDate" }, + { .val = KMIP_TAG_ASYNCHRONOUS_CORRELATION_VALUE, + .name = "AsynchronousCorrelationValue" }, + { .val = KMIP_TAG_ASYNCHRONOUS_INDICATOR, + .name = "AsynchronousIndicator" }, + { .val = KMIP_TAG_ATTRIBUTE, .name = "Attribute" }, + { .val = KMIP_TAG_ATTRIBUTE_INDEX, .name = "AttributeIndex" }, + { .val = KMIP_TAG_ATTRIBUTE_NAME, .name = "AttributeName" }, + { .val = KMIP_TAG_ATTRIBUTE_VALUE, .name = "AttributeValue" }, + { .val = KMIP_TAG_AUTHENTICATION, .name = "Authentication" }, + { .val = KMIP_TAG_BATCH_COUNT, .name = "BatchCount" }, + { .val = KMIP_TAG_BATCH_ERROR_CONTINUATION_OPTION, + .name = "BatchErrorContinuationOption" }, + { .val = KMIP_TAG_BATCH_ITEM, .name = "BatchItem" }, + { .val = KMIP_TAG_BATCH_ORDER_OPTION, .name = "BatchOrderOption" }, + { .val = KMIP_TAG_BLOCK_CIPHER_MODE, .name = "BlockCipherMode" }, + { .val = KMIP_TAG_CANCELATION_RESULT, .name = "CancelationResult" }, + { .val = KMIP_TAG_CERTIFICATE, .name = "Certificate" }, + { .val = KMIP_TAG_CERTIFICATE_IDENTIFIER, + .name = "CertificateIndentifyer" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER, .name = "CertificateIssuer" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_ALTERNATIVE_NAME, + .name = "CertificateIssuerAlternativeName" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_DISTINGUISHED_NAME, + .name = "CertificateIssuerDistinguishedName" }, + { .val = KMIP_TAG_CERTIFICATE_REQUEST, + .name = "CertificateRequest" }, + { .val = KMIP_TAG_CERTIFICATE_REQUEST_TYPE, + .name = "CertificateRequestType" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT, .name = "CertificateSubject" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_ALTERNATIVE_NAME, + .name = "CertificateSubjectAlternativeName" }, + { .val = KMIP_TAG_CERTIFICATE_TYPE, .name = "CertificateType" }, + { .val = KMIP_TAG_CERTIFICATE_VALUE, .name = "CertificateValue" }, + { .val = KMIP_TAG_COMMON_TEMPLATE_ATTRIBUTE, + .name = "CommonTemplateAttribute" }, + { .val = KMIP_TAG_COMPROMIZE_DATE, .name = "CompromizeDate" }, + { .val = KMIP_TAG_COMPROMISE_OCCURRENCE_DATE, + .name = "CompromiseOccurrenceDate" }, + { .val = KMIP_TAG_CONTACT_INFORMATION, .name = "ContactInformation" }, + { .val = KMIP_TAG_CREDENTIAL, .name = "Credential" }, + { .val = KMIP_TAG_CREDENTIAL_TYPE, .name = "CredentialType" }, + { .val = KMIP_TAG_CREDENTIAL_VALUE, .name = "CredentialValue" }, + { .val = KMIP_TAG_CRITICALITY_INDICATOR, + .name = "CriticalityIndicator" }, + { .val = KMIP_TAG_CRT_Coefficient, .name = "CrtCoefficient" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, + .name = "CryptographicAlgorithm" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_DOMAIN_PARAMETERS, + .name = "CryptographicDomainParameters" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_LENGTH, .name = "CryptographicLength" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS, + .name = "CryptographicParameters" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK, + .name = "CryptographicUsageMask" }, + { .val = KMIP_TAG_CUSTOM_ATTRIBUTE, .name = "CustomAttribute" }, + { .val = KMIP_TAG_D, .name = "D" }, + { .val = KMIP_TAG_DEACTIVATION_DATE, .name = "DeactivationDate" }, + { .val = KMIP_TAG_DERIVATION_DATE, .name = "DerivationDate" }, + { .val = KMIP_TAG_DERIVATION_DATA, .name = "DerivationData" }, + { .val = KMIP_TAG_DERIVATION_PARAMETERS, + .name = "DerivationParameters" }, + { .val = KMIP_TAG_DESTROY_DATE, .name = "DestroyDate" }, + { .val = KMIP_TAG_DIGEST, .name = "Digest" }, + { .val = KMIP_TAG_DIGEST_VALUE, .name = "DigestValue" }, + { .val = KMIP_TAG_ENCRYPTION_KEY_INFORMATION, + .name = "EncryptionKeyInformation" }, + { .val = KMIP_TAG_G, .name = "G" }, + { .val = KMIP_TAG_HASHING_ALGORITHM, .name = "HashingAlgorithm" }, + { .val = KMIP_TAG_INITIAL_DATE, .name = "InitialDate" }, + { .val = KMIP_TAG_INITIALIZATION_VECTOR, + .name = "InitializationVector" }, + { .val = KMIP_TAG_ISSUER, .name = "Issuer" }, + { .val = KMIP_TAG_ITERATION_COUNT, .name = "IterationCount" }, + { .val = KMIP_TAG_IV_COUNTER_NONCE, .name = "IvCounterNonce" }, + { .val = KMIP_TAG_J, .name = "J" }, + { .val = KMIP_TAG_KEY, .name = "Key" }, + { .val = KMIP_TAG_KEY_BLOCK, .name = "KeyBlock" }, + { .val = KMIP_TAG_KEY_COMPRESSION_TYPE, .name = "KeyCompressionType" }, + { .val = KMIP_TAG_KEY_FORMAT_TYPE, .name = "KeyFormatType" }, + { .val = KMIP_TAG_KEY_MATERIAL, .name = "KeyMaterial" }, + { .val = KMIP_TAG_KEY_PART_IDENTIFIER, .name = "KeyPartIdentifier" }, + { .val = KMIP_TAG_KEY_VALUE, .name = "KeyValue" }, + { .val = KMIP_TAG_KEY_WRAPPING_DATA, .name = "KeyWrappingData" }, + { .val = KMIP_TAG_KEY_WRAPPING_SPECIFICATION, + .name = "KeyWrappingSpecification" }, + { .val = KMIP_TAG_LAST_CHANGE_DATE, .name = "LastChangeDate" }, + { .val = KMIP_TAG_LEASE_TIME, .name = "LeaseTime" }, + { .val = KMIP_TAG_LINK, .name = "Link" }, + { .val = KMIP_TAG_LINK_TYPE, .name = "LinkType" }, + { .val = KMIP_TAG_LINKED_OBJECT_IDENTIFIER, + .name = "LinkedObjectIdentifier" }, + { .val = KMIP_TAG_MAC_SIGNATURE, .name = "MACSignature" }, + { .val = KMIP_TAG_MAC_SIGNATURE_KEY_INFORMATION, + .name = "MACSignatureKeyInformation" }, + { .val = KMIP_TAG_MAXIMUM_ITEMS, .name = "MaximumItems" }, + { .val = KMIP_TAG_MAXIMUM_RESPONSE_SIZE, + .name = "MaximumResponseSize" }, + { .val = KMIP_TAG_MESSAGE_EXTENSION, .name = "MessageExtension" }, + { .val = KMIP_TAG_MODULUS, .name = "Modulus" }, + { .val = KMIP_TAG_NAME, .name = "Name" }, + { .val = KMIP_TAG_NAME_TYPE, .name = "NameType" }, + { .val = KMIP_TAG_NAME_VALUE, .name = "NameValue" }, + { .val = KMIP_TAG_OBJECT_GROUP, .name = "ObjectGroup" }, + { .val = KMIP_TAG_OBJECT_TYPE, .name = "ObjectType" }, + { .val = KMIP_TAG_OFFSET, .name = "Offset" }, + { .val = KMIP_TAG_OPAQUE_DATA_TYPE, .name = "OpaqueDataType" }, + { .val = KMIP_TAG_OPAQUE_DATA_VALUE, .name = "OpaqueDataValue" }, + { .val = KMIP_TAG_OPAQUE_OBJECT, .name = "OpaqueObject" }, + { .val = KMIP_TAG_OPERATION, .name = "Operation" }, + { .val = KMIP_TAG_OPERATION_POLICY_NAME, + .name = "OperationPolicyName" }, + { .val = KMIP_TAG_P, .name = "P" }, + { .val = KMIP_TAG_PADDING_METHOD, .name = "PaddingMethod" }, + { .val = KMIP_TAG_PRIME_EXPONENT_P, .name = "PrimeExponentP" }, + { .val = KMIP_TAG_PRIME_EXPONENT_Q, .name = "PrimeExponentQ" }, + { .val = KMIP_TAG_PRIME_FIELD_SIZE, .name = "PrimeFieldSize" }, + { .val = KMIP_TAG_PRIVATE_EXPONENT, .name = "PrivateExponent" }, + { .val = KMIP_TAG_PRIVATE_KEY, .name = "PrivateKey" }, + { .val = KMIP_TAG_PRIVATE_KEY_TEMPLATE_ATTRIBUTE, + .name = "PrivateKeyTemplateAttribute" }, + { .val = KMIP_TAG_PRIVATE_KEY_UNIQUE_IDENTIFIER, + .name = "PrivateKeyUniqueIdentifier" }, + { .val = KMIP_TAG_PROCESS_START_DATE, .name = "ProcessStartDate" }, + { .val = KMIP_TAG_PROTECT_STOP_DATE, .name = "ProtectStopDate" }, + { .val = KMIP_TAG_PROTOCOL_VERSION, .name = "ProtocolVersion" }, + { .val = KMIP_TAG_PROTOCOL_VERSION_MAJOR, + .name = "ProtocolVersionMajor" }, + { .val = KMIP_TAG_PROTOCOL_VERSION_MINOR, + .name = "ProtocolVersionMinor" }, + { .val = KMIP_TAG_PUBLIC_EXPONENT, .name = "PublicExponent" }, + { .val = KMIP_TAG_PUBLIC_KEY, .name = "PublicKey" }, + { .val = KMIP_TAG_PUBLIC_KEY_TEMPLATE_ATTRIBUTE, + .name = "PublicKeyTemplateAttribute" }, + { .val = KMIP_TAG_PUBLIC_KEY_UNIQUE_IDENTIFIER, + .name = "PublicKeyUniqueIdentifier" }, + { .val = KMIP_TAG_PUT_FUNCTION, .name = "PutFunction" }, + { .val = KMIP_TAG_Q, .name = "Q" }, + { .val = KMIP_TAG_Q_STRING, .name = "QString" }, + { .val = KMIP_TAG_Q_LENGTH, .name = "QLength" }, + { .val = KMIP_TAG_QUERY_FUNCTION, .name = "QueryFunction" }, + { .val = KMIP_TAG_RECOMMENDED_CURVE, .name = "RecommendedCurve" }, + { .val = KMIP_TAG_REPLACED_UNIQUE_IDENTIFIER, + .name = "ReplacedUniqueIdentifier" }, + { .val = KMIP_TAG_REQUEST_HEADER, .name = "RequestHeader" }, + { .val = KMIP_TAG_REQUEST_MESSAGE, .name = "RequestMessage" }, + { .val = KMIP_TAG_REQUEST_PAYLOAD, .name = "RequestPayload" }, + { .val = KMIP_TAG_RESPONSE_HEADER, .name = "ResponseHeader" }, + { .val = KMIP_TAG_RESPONSE_MESSAGE, .name = "ResponseMessage" }, + { .val = KMIP_TAG_RESPONSE_PAYLOAD, .name = "ResponsePayload" }, + { .val = KMIP_TAG_RESULT_MESSAGE, .name = "ResultMessage" }, + { .val = KMIP_TAG_RESULT_REASON, .name = "ResultReason" }, + { .val = KMIP_TAG_RESULT_STATUS, .name = "ResultStatus" }, + { .val = KMIP_TAG_REVOCATION_MESSAGE, .name = "RevocationMessage" }, + { .val = KMIP_TAG_REVOCATION_REASON, .name = "RevocationReason" }, + { .val = KMIP_TAG_REVOCATION_REASON_CODE, + .name = "RevocationReasonCode" }, + { .val = KMIP_TAG_KEY_ROLE_TYPE, .name = "KeyRoleType" }, + { .val = KMIP_TAG_SALT, .name = "Salt" }, + { .val = KMIP_TAG_SECRET_DATA, .name = "SecretData" }, + { .val = KMIP_TAG_SECRET_DATA_TYPE, .name = "SecretDataType" }, + { .val = KMIP_TAG_SERIAL_NUMBER, .name = "SerialNumber" }, + { .val = KMIP_TAG_SERVER_INFORMATION, .name = "ServerInformation" }, + { .val = KMIP_TAG_SPLIT_KEY, .name = "SplitKey" }, + { .val = KMIP_TAG_SPLIT_KEY_METHOD, .name = "SplitKeyMethod" }, + { .val = KMIP_TAG_SPLIT_KEY_PARTS, .name = "SplitKeyParts" }, + { .val = KMIP_TAG_SPLIT_KEY_THRESHOLD, .name = "SplitKeyThreshold" }, + { .val = KMIP_TAG_STATE, .name = "State" }, + { .val = KMIP_TAG_STORAGE_STATUS_MASK, .name = "StorageStatusMask" }, + { .val = KMIP_TAG_SYMMETRIC_KEY, .name = "SymmetricKey" }, + { .val = KMIP_TAG_TEMPLATE, .name = "Template" }, + { .val = KMIP_TAG_TEMPLATE_ATTRIBUTE, .name = "TemplateAttribute" }, + { .val = KMIP_TAG_TIME_STAMP, .name = "TimeStamp" }, + { .val = KMIP_TAG_UNIQUE_BATCH_ITEM_ID, .name = "UniqueBatchItemId" }, + { .val = KMIP_TAG_UNIQUE_IDENTIFIER, .name = "UniqueIdentifier" }, + { .val = KMIP_TAG_USAGE_LIMITS, .name = "UsageLimits" }, + { .val = KMIP_TAG_USAGE_LIMITS_COUNT, .name = "UsageLimitsCount" }, + { .val = KMIP_TAG_USAGE_LIMITS_TOTAL, .name = "UsageLimitsTotal" }, + { .val = KMIP_TAG_USAGE_LIMITS_UNIT, .name = "UsageLimitsUnit" }, + { .val = KMIP_TAG_USERNAME, .name = "Username" }, + { .val = KMIP_TAG_VALIDITY_DATE, .name = "ValidityDate" }, + { .val = KMIP_TAG_VALIDITY_INDICATOR, .name = "ValidityIndicator" }, + { .val = KMIP_TAG_VENDOR_EXTENSION, .name = "VendorExtension" }, + { .val = KMIP_TAG_VENDOR_IDENTIFICATION, + .name = "VendorIdentification" }, + { .val = KMIP_TAG_WRAPPING_METHOD, .name = "WrappingMethod" }, + { .val = KMIP_TAG_X, .name = "X" }, + { .val = KMIP_TAG_Y, .name = "Y" }, + { .val = KMIP_TAG_PASSWORD, .name = "Password" }, + { .val = KMIP_TAG_DEVICE_IDENTIFIER, .name = "DeviceIdentifier" }, + { .val = KMIP_TAG_ENCODING_OPTION, .name = "EncodingOption" }, + { .val = KMIP_TAG_EXTENSION_INFORMATION, + .name = "ExtensionInformation" }, + { .val = KMIP_TAG_EXTENSION_NAME, .name = "ExtensionName" }, + { .val = KMIP_TAG_EXTENSION_TAG, .name = "ExtensionTag" }, + { .val = KMIP_TAG_EXTENSION_TYPE, .name = "ExtensionType" }, + { .val = KMIP_TAG_FRESH, .name = "Fresh" }, + { .val = KMIP_TAG_MACHINE_IDENTIFIER, .name = "MachineIdentifier" }, + { .val = KMIP_TAG_MEDIA_IDENTIFIER, .name = "MediaIdentifier" }, + { .val = KMIP_TAG_NETWORK_IDENTIFIER, .name = "NetworkIdentifier" }, + { .val = KMIP_TAG_OBJECT_GROUP_MEMBER, .name = "ObjectGroupMember" }, + { .val = KMIP_TAG_CERTIFICATE_LENGTH, .name = "CertificateLength" }, + { .val = KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM, + .name = "DigitalSignatureAlgorithm" }, + { .val = KMIP_TAG_CERTIFICATE_SERIAL_NUMBER, + .name = "CertificateSerialNumber" }, + { .val = KMIP_TAG_DEVICE_SERIAL_NUMBER, + .name = "DeviceSerialNumber" }, + { .val = KMIP_TAG_ISSUER_ALTERNATE_NAME, + .name = "IssuerAlternateName" }, + { .val = KMIP_TAG_ISSUER_DISTINGUISHED_NAME, + .name = "IssuerDistinguishedName" }, + { .val = KMIP_TAG_SUBJECT_ALTERNATE_NAME, + .name = "SubjectAlternateName" }, + { .val = KMIP_TAG_SUBJECT_DISTINGUISHED_NAME, + .name = "SubjectDistinguishedName" }, + { .val = KMIP_TAG_X_509_CERTIFICATE_IDENTIFIER, + .name = "X_509CertificateIdentifier" }, + { .val = KMIP_TAG_X_509_CERTIFICATE_ISSUER, + .name = "X_509CertificateIssuer" }, + { .val = KMIP_TAG_X_509_CERTIFICATE_SUBJECT, + .name = "X_509CertificateSubject" }, + { .val = KMIP_TAG_KEY_VALUE_LOCATION, + .name = "KeyValueLocation" }, + { .val = KMIP_TAG_KEY_VALUE_LOCATION_VALUE, + .name = "KeyValueLocationValue" }, + { .val = KMIP_TAG_KEY_VALUE_LOCATION_TYPE, + .name = "KeyValueLocationType" }, + { .val = KMIP_TAG_KEY_VALUE_PRESENT, .name = "KeyValuePresent" }, + { .val = KMIP_TAG_ORIGINAL_CREATION_DATE, + .name = "OriginalCreationDate" }, + { .val = KMIP_TAG_PGP_KEY, .name = "PGPKey" }, + { .val = KMIP_TAG_PGP_KEY_VERSION, .name = "PGPKeyVersion" }, + { .val = KMIP_TAG_ALTERNATE_NAME, .name = "AlternateName" }, + { .val = KMIP_TAG_ALTERNATE_NAME_VALUE, .name = "AlternateNameValue" }, + { .val = KMIP_TAG_ALTERNATE_NAME_TYPE, .name = "AlternateNameType" }, + { .val = KMIP_TAG_DATA, .name = "Data" }, + { .val = KMIP_TAG_SIGNATURE_DATA, .name = "SignatureData" }, + { .val = KMIP_TAG_DATA_LENGTH, .name = "DataLength" }, + { .val = KMIP_TAG_RANDOM_IV, .name = "RandomIV" }, + { .val = KMIP_TAG_MAC_DATA, .name = "MACData" }, + { .val = KMIP_TAG_ATTESTATION_TYPE, .name = "AttestationType" }, + { .val = KMIP_TAG_NONCE, .name = "Nonce" }, + { .val = KMIP_TAG_NONCE_ID, .name = "NonceId" }, + { .val = KMIP_TAG_NONCE_VALUE, .name = "NonceValue" }, + { .val = KMIP_TAG_ATTESTATION_MEASUREMENT, + .name = "AttestationMeasurement" }, + { .val = KMIP_TAG_ATTESTATION_ASSERTION, + .name = "AttestationAssertion" }, + { .val = KMIP_TAG_IV_LENGTH, .name = "IVLength" }, + { .val = KMIP_TAG_TAG_LENGTH, .name = "TagLength" }, + { .val = KMIP_TAG_FIXED_FIELD_LENGTH, .name = "FixedFieldLength" }, + { .val = KMIP_TAG_COUNTER_LENGTH, .name = "CounterLength" }, + { .val = KMIP_TAG_INITIAL_COUNTER_VALUE, + .name = "InitialCounterValue" }, + { .val = KMIP_TAG_INVOCATION_FIELD_LENGTH, + .name = "InvocationFieldLength" }, + { .val = KMIP_TAG_ATTESTATION_CAPABLE_INDICATOR, + .name = "AttestationCapableIndicator" }, + { .val = KMIP_TAG_OFFSET_ITEMS, .name = "OffsetItems" }, + { .val = KMIP_TAG_LOCATED_ITEMS, .name = "LocatedItems" }, + { .val = KMIP_TAG_CORRELATION_VALUE, .name = "CorrelationValue" }, + { .val = KMIP_TAG_INIT_INDICATOR, .name = "InitIndicator" }, + { .val = KMIP_TAG_FINAL_INDICATOR, .name = "FinalIndicator" }, + { .val = KMIP_TAG_RNG_PARAMETERS, .name = "RNGParameters" }, + { .val = KMIP_TAG_RNG_ALGORITHM, .name = "RNGAlgorithm" }, + { .val = KMIP_TAG_DRBG_ALGORITHM, .name = "DRBGAlgorithm" }, + { .val = KMIP_TAG_FIPS186_VARIANT, .name = "Fips186Variant" }, + { .val = KMIP_TAG_PREDICTION_RESISTANCE, + .name = "PredictionResistance" }, + { .val = KMIP_TAG_RANDOM_NUMBER_GENERATOR, + .name = "RandomNumberGenerator" }, + { .val = KMIP_TAG_VALIDATION_INFORMATION, + .name = "ValidationInformation" }, + { .val = KMIP_TAG_VALIDATION_AUTHORITY_TYPE, + .name = "ValidationAuthorityType" }, + { .val = KMIP_TAG_VALIDATION_AUTHORITY_COUNTRY, + .name = "ValidationAuthorityCountry" }, + { .val = KMIP_TAG_VALIDATION_AUTHORITY_URI, + .name = "ValidationAuthorityURI" }, + { .val = KMIP_TAG_VALIDATION_VERSION_MAJOR, + .name = "ValidationVersionMajor" }, + { .val = KMIP_TAG_VALIDATION_VERSION_MINOR, + .name = "ValidationVersionMinor" }, + { .val = KMIP_TAG_VALIDATION_TYPE, .name = "ValidationType" }, + { .val = KMIP_TAG_VALIDATION_LEVEL, .name = "ValidationLevel" }, + { .val = KMIP_TAG_VALIDATION_CERTIFICATE_IDENTIFIER, + .name = "ValidationCertificateIdentifier" }, + { .val = KMIP_TAG_VALIDATION_CERTIFICATE_URI, + .name = "ValidationCertificateURI" }, + { .val = KMIP_TAG_VALIDATION_VENDOR_URI, + .name = "ValidationVendorURI" }, + { .val = KMIP_TAG_VALIDATION_PROFILE, .name = "ValidationProfile" }, + { .val = KMIP_TAG_PROFILE_INFORMATION, .name = "ProfileInformation" }, + { .val = KMIP_TAG_PROFILE_NAME, .name = "ProfileName" }, + { .val = KMIP_TAG_SERVER_URI, .name = "ServerURI" }, + { .val = KMIP_TAG_SERVER_PORT, .name = "ServerPort" }, + { .val = KMIP_TAG_STREAMING_CAPABILITY, .name = "StreamingCapability" }, + { .val = KMIP_TAG_ASYNCHRONOUS_CAPABILITY, + .name = "AsynchronousCapability" }, + { .val = KMIP_TAG_ATTESTATION_CAPABILITY, + .name = "AttestationCapability" }, + { .val = KMIP_TAG_UNWRAP_MODE, .name = "UnwrapMode" }, + { .val = KMIP_TAG_DESTROY_ACTION, .name = "DestroyAction" }, + { .val = KMIP_TAG_SHREDDING_ALGORITHM, .name = "ShreddingAlgorithm" }, + { .val = KMIP_TAG_RNG_MODE, .name = "RNGMode" }, + { .val = KMIP_TAG_CLIENT_REGISTRATION_METHOD, + .name = "ClientRegistrationMethod" }, + { .val = KMIP_TAG_CAPABILITY_INFORMATION, + .name = "CapabilityInformation" }, + { .val = KMIP_TAG_KEY_WRAP_TYPE, .name = "KeyWrapType" }, + { .val = KMIP_TAG_BATCH_UNDO_CAPABILITY, + .name = "BatchUndoCapability" }, + { .val = KMIP_TAG_BATCH_CONTINUE_CAPABILITY, + .name = "BatchContinueCapability" }, + { .val = KMIP_TAG_PKCS_12_FRIENDLY_NAME, + .name = "PKCS_12FriendlyName" }, + { .val = KMIP_TAG_DESCRIPTION, .name = "Description" }, + { .val = KMIP_TAG_COMMENT, .name = "Comment" }, + { .val = KMIP_TAG_AUTHENTICATED_ENCRYPTION_ADDITIONAL_DATA, + .name = "AuthenticatedEncryptionAdditionalDat" }, + { .val = KMIP_TAG_AUTHENTICTAED_ENCRYPTION_TAG, + .name = "AuthentictaedEncryptionTag" }, + { .val = KMIP_TAG_SALT_LENGTH, .name = "SaltLength" }, + { .val = KMIP_TAG_MASK_GENERATOR, .name = "MaskGenerator" }, + { .val = KMIP_TAG_MASK_GENERATOR_HASHING_ALGORITHM, + .name = "MaskGeneratorHashingAlgorithm" }, + { .val = KMIP_TAG_P_SOURCE, .name = "PSource" }, + { .val = KMIP_TAG_TRAILER_FIELD, .name = "TrailerField" }, + { .val = KMIP_TAG_CLIENT_CORRELATION_VALUE, + .name = "ClientCorrelationValue" }, + { .val = KMIP_TAG_SERVER_CORRELATION_VALUE, + .name = "ServerCorrelationValue" }, + { .val = KMIP_TAG_DIGESTED_DATA, .name = "DigestedData" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_CN, + .name = "CertificateSubjectCN" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_O, + .name = "CertificateSubjectO" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_OU, + .name = "CertificateSubjectOU" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_EMAIL, + .name = "CertificateSubjectEmail" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_C, + .name = "CertificateSubjectC" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_ST, + .name = "CertificateSubjectST" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_L, + .name = "CertificateSubjectL" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_UID, + .name = "CertificateSubjectUID" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_SERIAL_NUMBER, + .name = "CertificateSubjectSerialNumber" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_TITLE, + .name = "CertificateSubjectTitle" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_DC, + .name = "CertificateSubjectDC" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_DN_QUALIFIER, + .name = "CertificateSubjectDNQualifier" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_CN, + .name = "CertificateIssuerCN" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_O, .name = "CertificateIssuerO" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_OU, + .name = "CertificateIssuerOU" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_EMAIL, + .name = "CertificateIssuerEmail" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_C, .name = "CertificateIssuerC" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_ST, + .name = "CertificateIssuerST" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_L, .name = "CertificateIssuerL" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_UID, + .name = "CertificateIssuerUID" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_SERIAL_NUMBER, + .name = "CertificateIssuerSerialNumber" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_TITLE, + .name = "CertificateIssuerTitle" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_DC, + .name = "CertificateIssuerDC" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_DN_QUALIFIER, + .name = "CertificateIssuerDNQualifier" }, + { .val = KMIP_TAG_SENSITIVE, .name = "Sensitive" }, + { .val = KMIP_TAG_ALWAYS_SENSITIVE, .name = "AlwaysSensitive" }, + { .val = KMIP_TAG_EXTRACTABLE, .name = "Extractable" }, + { .val = KMIP_TAG_NEVER_EXTRACTABLE, .name = "NeverExtractable" }, + { .val = KMIP_TAG_REPLACE_EXISTING, .name = "ReplaceExisting" }, + { .val = KMIP_TAG_ATTRIBUTES, .name = "Attributes" }, + { .val = KMIP_TAG_COMMON_ATTRIBUTES, .name = "CommonAttributes" }, + { .val = KMIP_TAG_PRIVATE_KEY_ATTRIBUTES, + .name = "PrivateKeyAttributes" }, + { .val = KMIP_TAG_PUBLIC_KEY_ATTRIBUTES, + .name = "PublicKeyAttributes" }, + { .val = KMIP_TAG_EXTENSION_ENUMERATION, + .name = "ExtensionEnumeration" }, + { .val = KMIP_TAG_EXTENSION_ATTRIBUTE, + .name = "ExtensionAttribute" }, + { .val = KMIP_TAG_EXTENSION_PARENT_STRUCTURE_TAG, + .name = "ExtensionParentStructureTag" }, + { .val = KMIP_TAG_EXTENSION_DESCRIPTION, + .name = "ExtensionDescription" }, + { .val = KMIP_TAG_SERVER_NAME, .name = "ServerName" }, + { .val = KMIP_TAG_SERVER_SERIAL_NUMBER, + .name = "ServerSerialNumber" }, + { .val = KMIP_TAG_SERVER_VERSION, .name = "ServerVersion" }, + { .val = KMIP_TAG_SERVER_LOAD, .name = "ServerLoad" }, + { .val = KMIP_TAG_PRODUCT_NAME, .name = "ProductName" }, + { .val = KMIP_TAG_BUILD_LEVEL, .name = "BuildLevel" }, + { .val = KMIP_TAG_BUILD_DATE, .name = "BuildDate" }, + { .val = KMIP_TAG_CLUSTER_INFO, .name = "ClusterInfo" }, + { .val = KMIP_TAG_ALTERNATE_FAILOVER_ENDPOINTS, + .name = "AlternateFailoverEndpoints" }, + { .val = KMIP_TAG_SHORT_UNIQUE_IDENTIFIER, + .name = "ShortUniqueIdentifier" }, + { .val = KMIP_TAG_TAG, .name = "Tag" }, + { .val = KMIP_TAG_CERTIFICATE_REQUEST_UNIQUE_IDENTIFIER, + .name = "CertificateRequestUniqueIdentifier" }, + { .val = KMIP_TAG_NIST_KEY_TYPE, .name = "NISTKeyType" }, + { .val = KMIP_TAG_ATTRIBUTE_REFERENCE, .name = "AttributeReference" }, + { .val = KMIP_TAG_CURRENT_ATTRIBUTE, .name = "CurrentAttribute" }, + { .val = KMIP_TAG_NEW_ATTRIBUTE, .name = "NewAttribute" }, + { .val = KMIP_TAG_CERTIFICATE_REQUEST_VALUE, + .name = "CertificateRequestValue" }, + { .val = KMIP_TAG_LOG_MESSAGE, .name = "LogMessage" }, + { .val = KMIP_TAG_PROFILE_VERSION, .name = "ProfileVersion" }, + { .val = KMIP_TAG_PROFILE_VERSION_MAJOR, + .name = "ProfileVersionMajor" }, + { .val = KMIP_TAG_PROFILE_VERSION_MINOR, + .name = "ProfileVersionMinor" }, + { .val = KMIP_TAG_PROTECTION_LEVEL, .name = "ProtectionLevel" }, + { .val = KMIP_TAG_PROTECTION_PERIOD, .name = "ProtectionPeriod" }, + { .val = KMIP_TAG_QUANTUM_SAFE, .name = "QuantumSafe" }, + { .val = KMIP_TAG_QUANTUM_SAFE_CAPABILITY, + .name = "QuantumSafeCapability" }, + { .val = KMIP_TAG_TICKET, .name = "Ticket" }, + { .val = KMIP_TAG_TICKET_TYPE, .name = "TicketType" }, + { .val = KMIP_TAG_TICKET_VALUE, .name = "TicketValue" }, + { .val = KMIP_TAG_REQUEST_COUNT, .name = "RequestCount" }, + { .val = KMIP_TAG_RIGHTS, .name = "Rights" }, + { .val = KMIP_TAG_OBJECTS, .name = "Objects" }, + { .val = KMIP_TAG_OPERATIONS, .name = "Operations" }, + { .val = KMIP_TAG_RIGHT, .name = "Right" }, + { .val = KMIP_TAG_ENDPOINT_ROLE, .name = "EndpointRole" }, + { .val = KMIP_TAG_DEFAULTS_INFORMATION, .name = "DefaultsInformation" }, + { .val = KMIP_TAG_OBJECT_DEFAULTS, .name = "ObjectDefaults" }, + { .val = KMIP_TAG_EPHEMERAL, .name = "Ephemeral" }, + { .val = KMIP_TAG_SERVER_HASHED_PASSWORD, + .name = "ServerHashedPassword" }, + { .val = KMIP_TAG_ONE_TIME_PASSWORD, .name = "OneTimePassword" }, + { .val = KMIP_TAG_HASHED_PASSWORD, .name = "HashedPassword" }, + { .val = KMIP_TAG_ADJUSTMENT_TYPE, .name = "AdjustmentType" }, + { .val = KMIP_TAG_PKCS_11_INTERFACE, .name = "PKCS_11Interface" }, + { .val = KMIP_TAG_PKCS_11_FUNCTION, .name = "PKCS_11Function" }, + { .val = KMIP_TAG_PKCS_11_INPUT_PARAMETERS, + .name = "PKCS_11InputParameters" }, + { .val = KMIP_TAG_PKCS_11_OUTPUT_PARAMETERS, + .name = "PKCS_11OutputParameters" }, + { .val = KMIP_TAG_PKCS_11_RETURN_CODE, + .name = "PKCS_11ReturnCode" }, + { .val = KMIP_TAG_PROTECTION_STORAGE_MASK, + .name = "ProtectionStorageMask" }, + { .val = KMIP_TAG_PROTECTION_STORAGE_MASKS, + .name = "ProtectionStorageMasks" }, + { .val = KMIP_TAG_INTEROP_FUNCTION, .name = "InteropFunction" }, + { .val = KMIP_TAG_INTEROP_IDENTIFIER, .name = "InteropIdentifier" }, + { .val = KMIP_TAG_ADJUSTMENT_VALUE, .name = "AdjustmentValue" }, + { .val = KMIP_TAG_COMMON_PROTECTION_STORAGE_MASKS, + .name = "CommonProtectionStorageMasks" }, + { .val = KMIP_TAG_PRIVATE_PROTECTION_STORAGE_MASKS, + .name = "PrivateProtectionStorageMasks" }, + { .val = KMIP_TAG_PUBLIC_PROTECTION_STORAGE_MASKS, + .name = "PublicProtectionStorageMasks" }, + { .val = KMIP_TAG_OBJECT_GROUPS, .name = "ObjectGroups" }, + { .val = KMIP_TAG_OBJECT_TYPES, .name = "ObjectTypes" }, + { .val = KMIP_TAG_CONSTRAINTS, .name = "Constraints" }, + { .val = KMIP_TAG_CONSTRAINT, .name = "Constraint" }, + { .val = KMIP_TAG_ROTATE_INTERVAL, .name = "RotateInterval" }, + { .val = KMIP_TAG_ROTATE_AUTOMATIC, .name = "RotateAutomatic" }, + { .val = KMIP_TAG_ROTATE_OFFSET, .name = "RotateOffset" }, + { .val = KMIP_TAG_ROTATE_DATE, .name = "RotateDate" }, + { .val = KMIP_TAG_ROTATE_GENERATION, .name = "RotateGeneration" }, + { .val = KMIP_TAG_ROTATE_NAME, .name = "RotateName" }, + { .val = KMIP_TAG_ROTATE_NAME_VALUE, .name = "RotateNameValue" }, + { .val = KMIP_TAG_ROTATE_NAME_TYPE, .name = "RotateNameType" }, + { .val = KMIP_TAG_ROTATE_LATEST, .name = "RotateLatest" }, + { .val = KMIP_TAG_ASYNCHRONOUS_REQUEST, .name = "AsynchronousRequest" }, + { .val = KMIP_TAG_SUBMISSION_DATE, .name = "SubmissionDate" }, + { .val = KMIP_TAG_PROCESSING_STAGE, .name = "ProcessingStage" }, + { .val = KMIP_TAG_ASYNCHRONOUS_CORRELATION_VALUES, + .name = "AsynchronousCorrelationValues" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_types[] = { + { .val = KMIP_TYPE_STRUCTURE, .name = "Structure" }, + { .val = KMIP_TYPE_INTEGER, .name = "Integer" }, + { .val = KMIP_TYPE_LONG_INTEGER, .name = "LongInteger" }, + { .val = KMIP_TYPE_BIG_INTEGER, .name = "BigInteger" }, + { .val = KMIP_TYPE_ENUMERATION, .name = "Enumeration" }, + { .val = KMIP_TYPE_BOOLEAN, .name = "Boolean" }, + { .val = KMIP_TYPE_TEXT_STRING, .name = "TextString" }, + { .val = KMIP_TYPE_BYTE_STRING, .name = "ByteString" }, + { .val = KMIP_TYPE_DATE_TIME, .name = "DateTime" }, + { .val = KMIP_TYPE_INTERVAL, .name = "Interval" }, + { .val = KMIP_TYPE_DATE_TIME_EXTENDED, .name = "DateTimeExtended" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_operations[] = { + { .val = KMIP_OPERATION_CREATE, .name = "Create" }, + { .val = KMIP_OPERATION_CREATE_KEY_PAIR, .name = "CreateKeyPair" }, + { .val = KMIP_OPERATION_REGISTER, .name = "Register" }, + { .val = KMIP_OPERATION_RE_KEY, .name = "ReKey" }, + { .val = KMIP_OPERATION_DERIVE_KEY, .name = "DeriveKey" }, + { .val = KMIP_OPERATION_CERTIFY, .name = "Certify" }, + { .val = KMIP_OPERATION_RE_CERTIFY, .name = "ReCertify" }, + { .val = KMIP_OPERATION_LOCATE, .name = "Locate" }, + { .val = KMIP_OPERATION_CHECK, .name = "Check" }, + { .val = KMIP_OPERATION_GET, .name = "Get" }, + { .val = KMIP_OPERATION_GET_ATTRIBUTES, .name = "GetAttributes" }, + { .val = KMIP_OPERATION_GET_ATTRIBUTE_LIST, + .name = "GetAttributeList" }, + { .val = KMIP_OPERATION_ADD_ATTRIBUTE, .name = "AddAttribute" }, + { .val = KMIP_OPERATION_MODIFY_ATTRIBUTE, .name = "ModifyAttribute" }, + { .val = KMIP_OPERATION_DELETE_ATTRIBUTE, .name = "DeleteAttribute" }, + { .val = KMIP_OPERATION_OBTAIN_LEASE, .name = "ObtainLease" }, + { .val = KMIP_OPERATION_GET_USAGE_ALLOCATION, + .name = "GetUsageAllocation" }, + { .val = KMIP_OPERATION_ACTIVATE, .name = "Activate" }, + { .val = KMIP_OPERATION_REVOKE, .name = "Revoke" }, + { .val = KMIP_OPERATION_DESTROY, .name = "Destroy" }, + { .val = KMIP_OPERATION_ARCHIVE, .name = "Archive" }, + { .val = KMIP_OPERATION_RECOVER, .name = "Recover" }, + { .val = KMIP_OPERATION_VALIDATE, .name = "Validate" }, + { .val = KMIP_OPERATION_QUERY, .name = "Query" }, + { .val = KMIP_OPERATION_CANCEL, .name = "Cancel" }, + { .val = KMIP_OPERATION_POLL, .name = "Poll" }, + { .val = KMIP_OPERATION_NOTIFY, .name = "Notify" }, + { .val = KMIP_OPERATION_PUT, .name = "Put" }, + { .val = KMIP_OPERATION_RE_KEY_KEY_PAIR, .name = "ReKeyKeyPair" }, + { .val = KMIP_OPERATION_DISCOVER_VERSIONS, .name = "DiscoverVersions" }, + { .val = KMIP_OPERATION_ENCRYPT, .name = "Encrypt" }, + { .val = KMIP_OPERATION_DECRYPT, .name = "Decrypt" }, + { .val = KMIP_OPERATION_SIGN, .name = "Sign" }, + { .val = KMIP_OPERATION_SIGNATURE_VERIFY, .name = "SignatureVerify" }, + { .val = KMIP_OPERATION_MAC, .name = "MAC" }, + { .val = KMIP_OPERATION_MAC_VERIFY, .name = "MACVerify" }, + { .val = KMIP_OPERATION_RNG_RETRIEVE, .name = "RNGRetrieve" }, + { .val = KMIP_OPERATION_RNG_SEED, .name = "RNGSeed" }, + { .val = KMIP_OPERATION_HASH, .name = "Hash" }, + { .val = KMIP_OPERATION_CREATE_SPLIT_KEY, .name = "CreateSplitKey" }, + { .val = KMIP_OPERATION_JOIN_SPLIT_KEY, .name = "JoinSplitKey" }, + { .val = KMIP_OPERATION_IMPORT, .name = "Import" }, + { .val = KMIP_OPERATION_EXPORT, .name = "Export" }, + { .val = KMIP_OPERATION_LOG, .name = "Log" }, + { .val = KMIP_OPERATION_LOGIN, .name = "Login" }, + { .val = KMIP_OPERATION_LOGOUT, .name = "Logout" }, + { .val = KMIP_OPERATION_DELEGATE_LOGIN, .name = "DelegateLogin" }, + { .val = KMIP_OPERATION_ADJUST_ATTRIBUTE, .name = "AdjustAttribute" }, + { .val = KMIP_OPERATION_SET_ATTRIBUTE, .name = "SetAttribute" }, + { .val = KMIP_OPERATION_SET_ENDPOINT_ROLE, .name = "SetEndpointRole" }, + { .val = KMIP_OPERATION_PKS_11, .name = "PKCS_11" }, + { .val = KMIP_OPERATION_INTEROP, .name = "Interop" }, + { .val = KMIP_OPERATION_RE_PROVISION, .name = "ReProvision" }, + { .val = KMIP_OPERATION_SET_DEFAULTS, .name = "SetDefaults" }, + { .val = KMIP_OPERATION_SET_CONSTRAINTS, .name = "SetConstraints" }, + { .val = KMIP_OPERATION_GET_CONSTRAINTS, .name = "GetConstraints" }, + { .val = KMIP_OPERATION_QUERY_ASYNCHRONOUS_REQUESTS, + .name = "QueryAsynchronousRequests" }, + { .val = KMIP_OPERATION_PROCESS, .name = "Process" }, + { .val = KMIP_OPERATION_PING, .name = "Ping" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_batch_error_cont_options[] = { + { .val = KMIP_BATCH_ERR_CONT_CONTINUE, .name = "Continue" }, + { .val = KMIP_BATCH_ERR_CONT_STOP, .name = "Stop" }, + { .val = KMIP_BATCH_ERR_CONT_UNDO, .name = "Undo" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_crypto_usage_masks[] = { + { .val = KMIP_CRY_USAGE_MASK_SIGN, .name = "Sign" }, + { .val = KMIP_CRY_USAGE_MASK_VERIFY, .name = "Verify" }, + { .val = KMIP_CRY_USAGE_MASK_ENCRYPT, .name = "Encrypt" }, + { .val = KMIP_CRY_USAGE_MASK_DECRYPT, .name = "Decrypt" }, + { .val = KMIP_CRY_USAGE_MASK_WRAP_KEY, .name = "WrapKey" }, + { .val = KMIP_CRY_USAGE_MASK_UNWRAP_KEY, .name = "UnwrapKey" }, + { .val = KMIP_CRY_USAGE_MASK_EXPORT, .name = "Export" }, + { .val = KMIP_CRY_USAGE_MASK_MAC_GENERATE, .name = "MACGenerate" }, + { .val = KMIP_CRY_USAGE_MASK_MAC_VERIFY, .name = "MACVerify" }, + { .val = KMIP_CRY_USAGE_MASK_DERIVE_KEY, .name = "DeriveKey" }, + { .val = KMIP_CRY_USAGE_MASK_CONTENT_COMMITMENT, + .name = "ContentCommitmentNonRepudiation" }, + { .val = KMIP_CRY_USAGE_MASK_KEY_AGREEMENT, .name = "KeyAgreement" }, + { .val = KMIP_CRY_USAGE_MASK_CERTIFICATE_SIGN, + .name = "CertificateSign" }, + { .val = KMIP_CRY_USAGE_MASK_CLR_SIGN, .name = "CRLSign" }, + { .val = KMIP_CRY_USAGE_MASK_GENERATE_CRYPTOGRAM, + .name = "GenerateCryptogram" }, + { .val = KMIP_CRY_USAGE_MASK_VALIDATE_CRYPTOGRAM, + .name = "ValidateCryptogram" }, + { .val = KMIP_CRY_USAGE_MASK_TRANSLATE_ENCRYPT, + .name = "TranslateEncrypt" }, + { .val = KMIP_CRY_USAGE_MASK_TRANSLATE_DECRYPT, + .name = "TranslateDecrypt" }, + { .val = KMIP_CRY_USAGE_MASK_TRANSLATE_WRAP, .name = "TranslateWrap" }, + { .val = KMIP_CRY_USAGE_MASK_TRANSLATE_UNWRAP, + .name = "TranslateUnwrap" }, + { .val = KMIP_CRY_USAGE_MASK_AUTHENTICATE, .name = "Authenticate" }, + { .val = KMIP_CRY_USAGE_MASK_UNRESTRICTED, .name = "Unrestricted" }, + { .val = KMIP_CRY_USAGE_MASK_FPE_ENCRYPT, .name = "FPEEncrypt" }, + { .val = KMIP_CRY_USAGE_MASK_FPE_DECRYPT, .name = "FPEDecrypt" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_result_statuses[] = { + { .val = KMIP_RESULT_STATUS_SUCCESS, .name = "Success" }, + { .val = KMIP_RESULT_STATUS_OPERATION_FAILED, + .name = "OperationFailed" }, + { .val = KMIP_RESULT_STATUS_OPERATION_PENDING, + .name = "OperationPending" }, + { .val = KMIP_RESULT_STATUS_OPERATION_UNDONE, + .name = "OperationUndone" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_result_reasons[] = { + { .val = KMIP_RESULT_REASON_ITEM_NOT_FOUND, .name = "ItemNotFound" }, + { .val = KMIP_RESULT_REASON_RESPONSE_TOO_LARGE, + .name = "ResponseTooLarge" }, + { .val = KMIP_RESULT_REASON_AUTH_NOT_SUCCESSFUL, + .name = "AuthenticationNotSuccessful" }, + { .val = KMIP_RESULT_REASON_INVALID_MESSAGE, .name = "InvalidMessage" }, + { .val = KMIP_RESULT_REASON_OPERATION_NOT_SUCCESSFUL, + .name = "OperationNotSupported" }, + { .val = KMIP_RESULT_REASON_MISSING_DATA, .name = "MissingData" }, + { .val = KMIP_RESULT_REASON_INVALIUD_FIELD, .name = "InvalidField" }, + { .val = KMIP_RESULT_REASON_FEATURE_NOT_SUPPORTED, + .name = "FeatureNotSupported" }, + { .val = KMIP_RESULT_REASON_OP_CANCELED_BY_REQUESTOR, + .name = "OperationCanceledByRequeste" }, + { .val = KMIP_RESULT_REASON_CRYPTOGRAPHIC_FAILURE, + .name = "CryptographicFailure" }, + { .val = KMIP_RESULT_REASON_ILLEGAL_OPERATION, + .name = "IllegalOperation" }, + { .val = KMIP_RESULT_REASON_PERMISSION_DENIED, + .name = "PermissionDenied" }, + { .val = KMIP_RESULT_REASON_OBJECT_ARCHIVED, + .name = "ObjectArchived" }, + { .val = KMIP_RESULT_REASON_INDEX_OUT_OF_BOUNDS, + .name = "IndexOutOfBounds" }, + { .val = KMIP_RESULT_REASON_APP_NAMESPACE_NOT_SUPPORTED, + .name = "ApplicationNamespaceNotSupported" }, + { .val = KMIP_RESULT_REASON_KEY_FORMAT_TYPE_NOT_SUPPORTED, + .name = "KeyFormatTypeNotSupported" }, + { .val = KMIP_RESULT_REASON_KEY_COMPRESSION_TYPE_NOT_SUPPORTED, + .name = "KeyCompressionTypeNotSupported" }, + { .val = KMIP_RESULT_REASON_ENCODING_OPTION_ERROR, + .name = "EncodingOptionError" }, + { .val = KMIP_RESULT_REASON_KEY_VALUE_NOT_PRESENT, + .name = "KeyValueNotPresent" }, + { .val = KMIP_RESULT_REASON_ATTESTATION_REQUIRED, + .name = "AttestationRequired" }, + { .val = KMIP_RESULT_REASON_ATTESTATION_FAILED, + .name = "AttestationFailed" }, + { .val = KMIP_RESULT_REASON_SENSITIVE, .name = "Sensitive" }, + { .val = KMIP_RESULT_REASON_NOT_EXTRACTABLE, .name = "NotExtractable" }, + { .val = KMIP_RESULT_REASON_OBJECT_ALREADY_EXISTS, + .name = "ObjectAlreadyExists" }, + { .val = KMIP_RESULT_REASON_INVALID_TICKET, .name = "InvalidTicket" }, + { .val = KMIP_RESULT_REASON_USAGE_LIMIT_EXCEEDED, + .name = "UsageLimitExceeded" }, + { .val = KMIP_RESULT_REASON_NUMERIC_RANGE, .name = "NumericRange" }, + { .val = KMIP_RESULT_REASON_INVALID_DATA_TYPE, + .name = "InvalidDataType" }, + { .val = KMIP_RESULT_REASON_READ_ONLY_ATTRIBUTE, + .name = "ReadOnlyAttribute" }, + { .val = KMIP_RESULT_REASON_MULTI_VALUED_ATTRIBUTE, + .name = "MultiValuedAttribute" }, + { .val = KMIP_RESULT_REASON_UNSUPPORTED_ATTRIBUTE, + .name = "UnsupportedAttribute" }, + { .val = KMIP_RESULT_REASON_ATTRIBUTE_INSTANCE_NOT_FOUND, + .name = "AttributeInstanceNotFound" }, + { .val = KMIP_RESULT_REASON_ATTRIBUTE_NOT_FOUND, + .name = "AttributeNotFound" }, + { .val = KMIP_RESULT_REASON_ATTRIBUTE_READ_ONLY, + .name = "AttributeReadOnly" }, + { .val = KMIP_RESULT_REASON_ATTRIBUTE_SINGLE_VALUED, + .name = "AttributeSingleValued" }, + { .val = KMIP_RESULT_REASON_BAD_CRYPTOGRAPHIC_PARAMETERS, + .name = "BadCryptographicParameters" }, + { .val = KMIP_RESULT_REASON_BAD_PASSWORD, .name = "BadPassword" }, + { .val = KMIP_RESULT_REASON_CODEC_ERROR, .name = "CodecError" }, + { .val = KMIP_RESULT_REASON_ILLEGAL_OBJECT_TYPE, + .name = "IllegalObjectType" }, + { .val = KMIP_RESULT_REASON_INCOMPATIBLE_CRYPTO_USAGE_MASK, + .name = "IncompatibleCryptographicUsageMask" }, + { .val = KMIP_RESULT_REASON_INTERNAL_SERVER_ERROR, + .name = "InternalServerError" }, + { .val = KMIP_RESULT_REASON_INVALID_ASYNC_CORRELATION_VALUE, + .name = "InvalidAsynchronousCorrelationValue" }, + { .val = KMIP_RESULT_REASON_INVALID_ATTRIBUTE, + .name = "InvalidAttribute" }, + { .val = KMIP_RESULT_REASON_INVALID_ATTRIBUTE_VALUE, + .name = "InvalidAttributeValue" }, + { .val = KMIP_RESULT_REASON_INVALID_CORRELATION_VALUE, + .name = "InvalidCorrelationValue" }, + { .val = KMIP_RESULT_REASON_INVALID_CSR, .name = "InvalidCSR" }, + { .val = KMIP_RESULT_REASON_INVALID_OBJECT_TYPE, + .name = "InvalidObjectType" }, + { .val = KMIP_RESULT_REASON_KEY_WRAP_TYPE_NOT_SUPPORTED, + .name = "KeyWrapTypeNotSupported" }, + { .val = KMIP_RESULT_REASON_MISSING_INITIALIZATION_VECTOR, + .name = "MissingInitializationVector" }, + { .val = KMIP_RESULT_REASON_NOT_UNIQUE_NAME_ATTRIBUTE, + .name = "NonUniqueNameAttribute" }, + { .val = KMIP_RESULT_REASON_OBJECT_DESTROYED, + .name = "ObjectDestroyed" }, + { .val = KMIP_RESULT_REASON_OBJECT_NOT_FOUND, + .name = "ObjectNotFound" }, + { .val = KMIP_RESULT_REASON_NOT_AUTHORISED, .name = "NotAuthorised" }, + { .val = KMIP_RESULT_REASON_SERVER_LIMIT_EXCEEDED, + .name = "ServerLimitExceeded" }, + { .val = KMIP_RESULT_REASON_UNKNOWN_ENUMERATION, + .name = "UnknownEnumeration" }, + { .val = KMIP_RESULT_REASON_UNKNOWN_MESSAGE_EXTENSION, + .name = "UnknownMessageExtension" }, + { .val = KMIP_RESULT_REASON_UNKNOWN_TAG, .name = "UnknownTag" }, + { .val = KMIP_RESULT_REASON_UNSUPPORTED_CRYPTO_PARAMETERS, + .name = "UnsupportedCryptographicParameters" }, + { .val = KMIP_RESULT_REASON_UNSUPPORTED_PROTOCOL_VERSION, + .name = "UnsupportedProtocolVersion" }, + { .val = KMIP_RESULT_REASON_WRAPPING_OBJECT_ARCHIVED, + .name = "WrappingObjectArchived" }, + { .val = KMIP_RESULT_REASON_WRAPPING_OBJECT_DESTROYED, + .name = "WrappingObjectDestroyed" }, + { .val = KMIP_RESULT_REASON_WRAPPING_OBJECT_NOT_FOUND, + .name = "WrappingObjectNotFound" }, + { .val = KMIP_RESULT_REASON_WRONG_KEY_LIFECYCLE_STATE, + .name = "WrongKeyLifecycleState" }, + { .val = KMIP_RESULT_REASON_PROTECTION_STORAGE_UNAVAILABLE, + .name = "ProtectionStorageUnavailable" }, + { .val = KMIP_RESULT_REASON_PKCS_11_CODE_ERROR, + .name = "PKCS_11CodecError" }, + { .val = KMIP_RESULT_REASON_PKCS_11_INVALID_FUNCTION, + .name = "PKCS_11InvalidFunction" }, + { .val = KMIP_RESULT_REASON_PKCS_11_INVALID_INTERFACE, + .name = "PKCS_11InvalidInterface" }, + { .val = KMIP_RESULT_REASON_PRIVATE_PROT_STORAGE_UNAVAILABLE, + .name = "PrivateProtectionStorageUnavailable" }, + { .val = KMIP_RESULT_REASON_PUBLIC_PROT_STORAGE_UNAVAILABLE, + .name = "PublicProtectionStorageUnavailable" }, + { .val = KMIP_RESULT_REASON_UNKNOWN_OBJECT_GROUP, + .name = "UnknownObjectGroup" }, + { .val = KMIP_RESULT_REASON_CONSTRAINT_VIOLATION, + .name = "ConstraintViolation" }, + { .val = KMIP_RESULT_REASON_DUPLICATE_PROCESS_REQUEST, + .name = "DuplicateProcessRequest" }, + { .val = KMIP_RESULT_REASON_GENERAL_FAILURE, .name = "GeneralFailure" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_query_functions[] = { + { .val = KMIP_QUERY_OPERATIONS, .name = "QueryOperations" }, + { .val = KMIP_QUERY_OBJECTS, .name = "QueryObjects" }, + { .val = KMIP_QUERY_SERVER_INFORMATION, + .name = "QueryServerInformation" }, + { .val = KMIP_QUERY_APPLICATION_NAMESPACES, + .name = "QueryApplicationNamespaces" }, + { .val = KMIP_QUERY_EXTENSION_LIST, .name = "QueryExtensionList" }, + { .val = KMIP_QUERY_EXTENSION_MAP, .name = "QueryExtensionMap" }, + { .val = KMIP_QUERY_ATTESTATION_TYPES, + .name = "QueryAttestationTypes" }, + { .val = KMIP_QUERY_QUERY_RNGS, .name = "QueryRNGs" }, + { .val = KMIP_QUERY_VALIDATIONS, .name = "QueryValidations" }, + { .val = KMIP_QUERY_PROFILES, .name = "QueryProfiles" }, + { .val = KMIP_QUERY_CAPABILITIES, .name = "QueryCapabilities" }, + { .val = KMIP_QUERY_CLIENT_REGISTRATION_METHODS, + .name = "QueryClientRegistrationMethods" }, + { .val = KMIP_QUERY_DEFAULTS_INFORMATION, + .name = "QueryDefaultsInformation" }, + { .val = KMIP_QUERY_STORAGE_PROTECTION_MASKS, + .name = "QueryStorageProtectionMasks" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_name_types[] = { + { .val = KMIP_NAME_TYPE_UNINTERPRETED_TEXT_STRING, + .name = "UninterpretedTextString" }, + { .val = KMIP_NAME_TYPE_URI, .name = "URI" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_alternate_name_types[] = { + { .val = KMIP_ALT_NAME_TYPE_UNINTERPRETED_TEXT_STRING, + .name = "UninterpretedTextString" }, + { .val = KMIP_ALT_NAME_TYPE_URI, .name = "URI" }, + { .val = KMIP_ALT_NAME_TYPE_OBJECT_SERIAL_NUMBER, + .name = "ObjectSerialNumber" }, + { .val = KMIP_ALT_NAME_TYPE_EMAIL_ADDRESS, .name = "EmailAddress" }, + { .val = KMIP_ALT_NAME_TYPE_DNS_NAME, .name = "DNSName" }, + { .val = KMIP_ALT_NAME_TYPE_X_500_DISTINGUISHED_NAME, + .name = "X_500DistinguishedName" }, + { .val = KMIP_ALT_NAME_TYPE_IP_ADDRESS, .name = "IPAddress" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_unique_identifiers[] = { + { .val = KMIP_UNIQUE_ID_ID_PLACEHOLDER, .name = "IDPlaceholder" }, + { .val = KMIP_UNIQUE_ID_CERTIFY, .name = "Certify" }, + { .val = KMIP_UNIQUE_ID_CREATE, .name = "Create" }, + { .val = KMIP_UNIQUE_ID_CREATE_KEY_PAIR, .name = "CreateKeyPair" }, + { .val = KMIP_UNIQUE_ID_CREATE_KEY_PAIR_PRIVATE, + .name = "CreateKeyPairPrivateKey" }, + { .val = KMIP_UNIQUE_ID_CREATE_KEY_PAIR_PUBLIC, + .name = "CreateKeyPairPublicKey" }, + { .val = KMIP_UNIQUE_ID_CREATE_SPLIT_KEY, .name = "CreateSplitKey" }, + { .val = KMIP_UNIQUE_ID_DERIVE_KEY, .name = "DeriveKey" }, + { .val = KMIP_UNIQUE_ID_IMPORT, .name = "Import" }, + { .val = KMIP_UNIQUE_ID_JOIN_SPLIT_KEY, .name = "JoinSplitKey" }, + { .val = KMIP_UNIQUE_ID_LOCATE, .name = "Locate" }, + { .val = KMIP_UNIQUE_ID_REGISTER, .name = "Register" }, + { .val = KMIP_UNIQUE_ID_RE_KEY, .name = "ReKey" }, + { .val = KMIP_UNIQUE_ID_RE_CERTIFY, .name = "ReCertify" }, + { .val = KMIP_UNIQUE_ID_RE_KEY_KEY_PAIR, .name = "ReKeyKeyPair" }, + { .val = KMIP_UNIQUE_ID_RE_KEY_KEY_PAIR_PRIVATE, + .name = "ReKeyKeyPairPrivateKey" }, + { .val = KMIP_UNIQUE_ID_RE_KEY_KEY_PAIR_PUBLIC, + .name = "ReKeyKeyPairPublicKey" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_object_types[] = { + { .val = KMIP_OBJECT_TYPE_CERTIFICATE, .name = "Certificate" }, + { .val = KMIP_OBJECT_TYPE_SYMMETRIC_KEY, .name = "SymmetricKey" }, + { .val = KMIP_OBJECT_TYPE_PUBLIC_KEY, .name = "PublicKey" }, + { .val = KMIP_OBJECT_TYPE_PRIVATE_KEY, .name = "PrivateKey" }, + { .val = KMIP_OBJECT_TYPE_SPLIT_KEY, .name = "SplitKey" }, + { .val = KMIP_OBJECT_TYPE_TEMPLATE, .name = "Template" }, + { .val = KMIP_OBJECT_TYPE_SECRET_DATA, .name = "SecretData" }, + { .val = KMIP_OBJECT_TYPE_OPAQUE_OBJECT, .name = "OpaqueObject" }, + { .val = KMIP_OBJECT_TYPE_PGP_KEY, .name = "PGPKey" }, + { .val = KMIP_OBJECT_TYPE_CERTIFICATE_REQUEST, + .name = "CertificateRequest" }, + { .val = 0, .name = NULL }, +}; + + +static const struct kmip_enum kmip_crypto_algos[] = { + { .val = KMIP_CRYPTO_ALGO_DES, .name = "DES" }, + { .val = KMIP_CRYPTO_ALGO_3DES, .name = "3DES" }, + { .val = KMIP_CRYPTO_ALGO_AES, .name = "AES" }, + { .val = KMIP_CRYPTO_ALGO_RSA, .name = "RSA" }, + { .val = KMIP_CRYPTO_ALGO_DSA, .name = "DSA" }, + { .val = KMIP_CRYPTO_ALGO_ECDSA, .name = "ECDSA" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA1, .name = "HMAC_SHA1" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA224, .name = "HMAC_SHA224" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA256, .name = "HMAC_SHA256" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA384, .name = "HMAC_SHA384" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA512, .name = "HMAC_SHA512" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_MD5, .name = "HMAC_MD5" }, + { .val = KMIP_CRYPTO_ALGO_DH, .name = "DH" }, + { .val = KMIP_CRYPTO_ALGO_ECDH, .name = "ECDH" }, + { .val = KMIP_CRYPTO_ALGO_ECMQV, .name = "ECMQV" }, + { .val = KMIP_CRYPTO_ALGO_BLOWFISH, .name = "Blowfish" }, + { .val = KMIP_CRYPTO_ALGO_CAMELLIA, .name = "Camellia" }, + { .val = KMIP_CRYPTO_ALGO_CAST5, .name = "CAST5" }, + { .val = KMIP_CRYPTO_ALGO_IDEA, .name = "IDEA" }, + { .val = KMIP_CRYPTO_ALGO_MARS, .name = "MARS" }, + { .val = KMIP_CRYPTO_ALGO_RC2, .name = "RC2" }, + { .val = KMIP_CRYPTO_ALGO_RC4, .name = "RC4" }, + { .val = KMIP_CRYPTO_ALGO_RC5, .name = "RC5" }, + { .val = KMIP_CRYPTO_ALGO_SKIPJACK, .name = "SKIPJACK" }, + { .val = KMIP_CRYPTO_ALGO_TWOFISH, .name = "Twofish" }, + { .val = KMIP_CRYPTO_ALGO_EC, .name = "EC" }, + { .val = KMIP_CRYPTO_ALGO_ONE_TIME_PAD, .name = "OneTimePad" }, + { .val = KMIP_CRYPTO_ALGO_CHACHA20, .name = "ChaCha20" }, + { .val = KMIP_CRYPTO_ALGO_POLY1305, .name = "Poly1305" }, + { .val = KMIP_CRYPTO_ALGO_CHACHA20_POLY1305, + .name = "ChaCha20Poly1305" }, + { .val = KMIP_CRYPTO_ALGO_SHA3_224, .name = "SHA3_224" }, + { .val = KMIP_CRYPTO_ALGO_SHA3_256, .name = "SHA3_256" }, + { .val = KMIP_CRYPTO_ALGO_SHA3_384, .name = "SHA3_384" }, + { .val = KMIP_CRYPTO_ALGO_SHA3_512, .name = "SHA3_512" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA3_224, .name = "HMAC_SHA3_224" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA3_256, .name = "HMAC_SHA3_256" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA3_384, .name = "HMAC_SHA3_384" }, + { .val = KMIP_CRYPTO_ALGO_HMAC_SHA3_512, .name = "HMAC_SHA3_512" }, + { .val = KMIP_CRYPTO_ALGO_SHAKE_128, .name = "SHAKE_128" }, + { .val = KMIP_CRYPTO_ALGO_SHAKE_256, .name = "SHAKE_256" }, + { .val = KMIP_CRYPTO_ALGO_ARIA, .name = "ARIA" }, + { .val = KMIP_CRYPTO_ALGO_SEED, .name = "SEED" }, + { .val = KMIP_CRYPTO_ALGO_SM2, .name = "SM2" }, + { .val = KMIP_CRYPTO_ALGO_SM3, .name = "SM3" }, + { .val = KMIP_CRYPTO_ALGO_SM4, .name = "SM4" }, + { .val = KMIP_CRYPTO_ALGO_GOST_R34_10_2012, .name = "GOSTR34_10_2012" }, + { .val = KMIP_CRYPTO_ALGO_GOST_R34_11_2012, .name = "GOSTR34_11_2012" }, + { .val = KMIP_CRYPTO_ALGO_GOST_R34_13_2015, .name = "GOSTR34_13_2015" }, + { .val = KMIP_CRYPTO_ALGO_GOST_28147_89, .name = "GOST28147_89" }, + { .val = KMIP_CRYPTO_ALGO_XMSS, .name = "XMSS" }, + { .val = KMIP_CRYPTO_ALGO_SPHINCS_256, .name = "SPHINCS_256" }, + { .val = KMIP_CRYPTO_ALGO_MCELIECE, .name = "McEliece" }, + { .val = KMIP_CRYPTO_ALGO_MCELIECE_6960119, + .name = "McEliece_6960119" }, + { .val = KMIP_CRYPTO_ALGO_MCELIECE_8192128, + .name = "McEliece_8192128" }, + { .val = KMIP_CRYPTO_ALGO_ED25519, .name = "Ed25519" }, + { .val = KMIP_CRYPTO_ALGO_ED448, .name = "Ed448" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_certificate_types[] = { + { .val = KMIP_CERTIFICATE_TYPE_X_509, .name = "X_509" }, + { .val = KMIP_CERTIFICATE_TYPE_PGP, .name = "PGP" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_states[] = { + { .val = KMIP_STATE_PRE_ACTIVE, .name = "PreActive" }, + { .val = KMIP_STATE_ACTIVE, .name = "Active" }, + { .val = KMIP_STATE_DEACTIVATED, .name = "Deactivated" }, + { .val = KMIP_STATE_COMPROMISED, .name = "Compromised" }, + { .val = KMIP_STATE_DESTROYED, .name = "Destroyed" }, + { .val = KMIP_STATE_DESTROYED_COMPROMISED, + .name = "DestroyedCompromised" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_protection_storage_masks[] = { + { .val = KMIP_PROT_STORAGE_MASK_SOFTWARE, .name = "Software" }, + { .val = KMIP_PROT_STORAGE_MASK_HARDWARE, .name = "Hardware" }, + { .val = KMIP_PROT_STORAGE_MASK_ON_PROCESSOR, .name = "OnProcessor" }, + { .val = KMIP_PROT_STORAGE_MASK_ON_SYSTEM, .name = "OnSystem" }, + { .val = KMIP_PROT_STORAGE_MASK_OFF_SYSTEM, .name = "OffSystem" }, + { .val = KMIP_PROT_STORAGE_MASK_HYPERVISOR, .name = "Hypervisor" }, + { .val = KMIP_PROT_STORAGE_MASK_OPERATING_SYSTEM, + .name = "OperatingSystem" }, + { .val = KMIP_PROT_STORAGE_MASK_CONTAINER, .name = "Container" }, + { .val = KMIP_PROT_STORAGE_MASK_ON_PREMISES, .name = "OnPremises" }, + { .val = KMIP_PROT_STORAGE_MASK_OFF_PREMISES, .name = "OffPremises" }, + { .val = KMIP_PROT_STORAGE_MASK_SELF_MANAGED, .name = "SelfManaged" }, + { .val = KMIP_PROT_STORAGE_MASK_OUTSOURCED, .name = "Outsourced" }, + { .val = KMIP_PROT_STORAGE_MASK_VALIDATED, .name = "Validated" }, + { .val = KMIP_PROT_STORAGE_MASK_SAME_JURISDICATION, + .name = "SameJurisdiction" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_revoke_reasons[] = { + { .val = KMIP_REVOK_RSN_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_REVOK_RSN_KEY_COMPROMISE, .name = "KeyCompromise" }, + { .val = KMIP_REVOK_RSN_CA_COMPROMISE, .name = "CACompromise" }, + { .val = KMIP_REVOK_RSN_AFFILIATION_CHANGED, + .name = "AffiliationChanged" }, + { .val = KMIP_REVOK_RSN_SUPERSEDED, .name = "Superseded" }, + { .val = KMIP_REVOK_RSN_CESSATION_OF_OPERATION, + .name = "CessationOfOperation" }, + { .val = KMIP_REVOK_RSN_PRIVILEGE_WITHDRAWN, + .name = "PrivilegeWithdrawn" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_object_group_members[] = { + { .val = KMIP_OBJ_GROUP_MEMBER_FRESH, .name = "GroupMemberFresh" }, + { .val = KMIP_OBJ_GROUP_MEMBER_DEFAULT, .name = "GroupMemberDefault" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_storage_status_masks[] = { + { .val = KMIP_STORAGE_STATUS_MASK_ONLINE, .name = "OnLineStorage" }, + { .val = KMIP_STORAGE_STATUS_MASK_ARCHIVAL, .name = "ArchivalStorage" }, + { .val = KMIP_STORAGE_STATUS_MASK_DESTTROYED, + .name = "DestroyedStorage" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_key_format_types[] = { + { .val = KMIP_KEY_FORMAT_TYPE_RAW, .name = "Raw" }, + { .val = KMIP_KEY_FORMAT_TYPE_OPAQUE, .name = "Opaque" }, + { .val = KMIP_KEY_FORMAT_TYPE_PKCS_1, .name = "PKCS_1" }, + { .val = KMIP_KEY_FORMAT_TYPE_PKCS_8, .name = "PKCS_8" }, + { .val = KMIP_KEY_FORMAT_TYPE_X_509, .name = "X_509" }, + { .val = KMIP_KEY_FORMAT_TYPE_EC_PRIVATE_KEY, .name = "ECPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_SYMMETRIC_KEY, + .name = "TransparentSymmetricKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DSA_PRIVATE_KEY, + .name = "TransparentDSAPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DSA_PUBLIC_KEY, + .name = "TransparentDSAPublicKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_RSA_PRIVATE_KEY, + .name = "TransparentRSAPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_RSA_PUBLIC_KEY, + .name = "TransparentRSAPublicKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DH_PRIVATE_KEY, + .name = "TransparentDHPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_DH_PUBLIC_KEY, + .name = "TransparentDHPublicKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDSA_PRIVATE_KEY, + .name = "TransparentECDSAPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDSA_PUBLIC_KEY, + .name = "TransparentECDSAPublicKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDH_PRIVATE_KEY, + .name = "TransparentECDHPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECDH_PUBLIC_KEY, + .name = "TransparentECDHPublicKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECMQV_PRIVATE_KEY, + .name = "TransparentECMQVPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_ECMQV_PUBLIC_KEY, + .name = "TransparentECMQVPublicKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_EC_PRIVATE_KEY, + .name = "TransparentECPrivateKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_TRANSPARENT_EC_PUBLIC_KEY, + .name = "TransparentECPublicKey" }, + { .val = KMIP_KEY_FORMAT_TYPE_PKCS_12, .name = "PKCS_12" }, + { .val = KMIP_KEY_FORMAT_TYPE_PKCS_10, .name = "PKCS_10" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_key_compression_types[] = { + { .val = KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_UNCOMPRESSED, + .name = "ECPublicKeyTypeUncompressed" }, + { .val = KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_COMPRESSED_PRIME, + .name = "ECPublicKeyTypeX9_62CompressedPrime" }, + { .val = KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_COMPRESSED_CHAR2, + .name = "ECPublicKeyTypeX9_62CompressedChar2" }, + { .val = KMIP_KEY_COMPRESSION_TYPE_EC_PUBKEY_HYBID, + .name = "ECPublicKeyTypeX9_62Hybrid" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_wrapping_methods[] = { + { .val = KMIP_WRAPPING_METHOD_ENCRYPT, .name = "Encrypt" }, + { .val = KMIP_WRAPPING_METHOD_MAC_SIGN, .name = "MAC_sign" }, + { .val = KMIP_WRAPPING_METHOD_ENCRYPT_THEN_MAC_SIGN, + .name = "EncryptThenMAC_sign" }, + { .val = KMIP_WRAPPING_METHOD_MAC_SIGN_THEN_ENCRYPT, + .name = "MAC_signThenEncrypt" }, + { .val = KMIP_WRAPPING_METHOD_TR_31, .name = "TR_31" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_key_wrap_types[] = { + { .val = KMIP_KEY_WRAP_TYPE_NOT_WRAPPED, .name = "NotWrapped" }, + { .val = KMIP_KEY_WRAP_TYPE_AS_REGISTERED, .name = "AsRegistered" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_block_cipher_modes[] = { + { .val = KMIP_BLOCK_CIPHER_MODE_CBC, .name = "CBC" }, + { .val = KMIP_BLOCK_CIPHER_MODE_ECB, .name = "ECB" }, + { .val = KMIP_BLOCK_CIPHER_MODE_PCBC, .name = "PCBC" }, + { .val = KMIP_BLOCK_CIPHER_MODE_CFB, .name = "CFB" }, + { .val = KMIP_BLOCK_CIPHER_MODE_OFB, .name = "OFB" }, + { .val = KMIP_BLOCK_CIPHER_MODE_CTR, .name = "CTR" }, + { .val = KMIP_BLOCK_CIPHER_MODE_CMAC, .name = "CMAC" }, + { .val = KMIP_BLOCK_CIPHER_MODE_CCM, .name = "CCM" }, + { .val = KMIP_BLOCK_CIPHER_MODE_GCM, .name = "GCM" }, + { .val = KMIP_BLOCK_CIPHER_MODE_CBC_MAC, .name = "CBC_MAC" }, + { .val = KMIP_BLOCK_CIPHER_MODE_XTS, .name = "XTS" }, + { .val = KMIP_BLOCK_CIPHER_MODE_AES_KEY_WRAP_PADDING, + .name = "AESKeyWrapPadding" }, + { .val = KMIP_BLOCK_CIPHER_MODE_NIST_KEY_WRAP, .name = "NISTKeyWrap" }, + { .val = KMIP_BLOCK_CIPHER_MODE_X9_102_AESKW, .name = "X9_102AESKW" }, + { .val = KMIP_BLOCK_CIPHER_MODE_X9_102_TDKW, .name = "X9_102TDKW" }, + { .val = KMIP_BLOCK_CIPHER_MODE_X9_102_AKW1, .name = "X9_102AKW1" }, + { .val = KMIP_BLOCK_CIPHER_MODE_X9_102_AKW2, .name = "X9_102AKW2" }, + { .val = KMIP_BLOCK_CIPHER_MODE_AEAD, .name = "AEAD" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_padding_methods[] = { + { .val = KMIP_PADDING_METHOD_NONE, .name = "None" }, + { .val = KMIP_PADDING_METHOD_OAEP, .name = "OAEP" }, + { .val = KMIP_PADDING_METHOD_PKCS5, .name = "PKCS5" }, + { .val = KMIP_PADDING_METHOD_SSL3, .name = "SSL3" }, + { .val = KMIP_PADDING_METHOD_ZEROS, .name = "Zeros" }, + { .val = KMIP_PADDING_METHOD_ANSI_X9_23, .name = "ANSIX9_23" }, + { .val = KMIP_PADDING_METHOD_ISO_10126, .name = "ISO10126" }, + { .val = KMIP_PADDING_METHOD_PKCS_1_5, .name = "PKCS1V1_5" }, + { .val = KMIP_PADDING_METHOD_X9_31, .name = "X9_31" }, + { .val = KMIP_PADDING_METHOD_PSS, .name = "PSS" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_hashing_algos[] = { + { .val = KMIP_HASHING_ALGO_MD2, .name = "MD2" }, + { .val = KMIP_HASHING_ALGO_MD4, .name = "MD4" }, + { .val = KMIP_HASHING_ALGO_MD5, .name = "MD5" }, + { .val = KMIP_HASHING_ALGO_SHA_1, .name = "SHA_1" }, + { .val = KMIP_HASHING_ALGO_SHA_224, .name = "SHA_224" }, + { .val = KMIP_HASHING_ALGO_SHA_256, .name = "SHA_256" }, + { .val = KMIP_HASHING_ALGO_SHA_384, .name = "SHA_384" }, + { .val = KMIP_HASHING_ALGO_SHA_512, .name = "SHA_512" }, + { .val = KMIP_HASHING_ALGO_RIPEMD_160, .name = "RIPEMD_160" }, + { .val = KMIP_HASHING_ALGO_TIGER, .name = "Tiger" }, + { .val = KMIP_HASHING_ALGO_WIRLPOOL, .name = "Whirlpool" }, + { .val = KMIP_HASHING_ALGO_SHA_512_224, .name = "SHA_512_224" }, + { .val = KMIP_HASHING_ALGO_SHA_512_256, .name = "SHA_512_256" }, + { .val = KMIP_HASHING_ALGO_SHA_3_224, .name = "SHA3_224" }, + { .val = KMIP_HASHING_ALGO_SHA_3_256, .name = "SHA3_256" }, + { .val = KMIP_HASHING_ALGO_SHA_3_384, .name = "SHA3_384" }, + { .val = KMIP_HASHING_ALGO_SHA_3_512, .name = "SHA3_512" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_key_role_types[] = { + { .val = KMIP_KEY_ROLE_TYPE_BDK, .name = "BDK" }, + { .val = KMIP_KEY_ROLE_TYPE_CVK, .name = "CVK" }, + { .val = KMIP_KEY_ROLE_TYPE_DEK, .name = "DEK" }, + { .val = KMIP_KEY_ROLE_TYPE_KMAC, .name = "KMAC" }, + { .val = KMIP_KEY_ROLE_TYPE_MKSMC, .name = "MKSMC" }, + { .val = KMIP_KEY_ROLE_TYPE_MKSMI, .name = "MKSMI" }, + { .val = KMIP_KEY_ROLE_TYPE_MKDAC, .name = "_MKDAC" }, + { .val = KMIP_KEY_ROLE_TYPE_MKDN, .name = "MKDN" }, + { .val = KMIP_KEY_ROLE_TYPE_MKCP, .name = "MKCP" }, + { .val = KMIP_KEY_ROLE_TYPE_MKOTH, .name = "MKOTH" }, + { .val = KMIP_KEY_ROLE_TYPE_KEK, .name = "KEK" }, + { .val = KMIP_KEY_ROLE_TYPE_MAC16609, .name = "MAC16609" }, + { .val = KMIP_KEY_ROLE_TYPE_MAC97971, .name = "MAC97971" }, + { .val = KMIP_KEY_ROLE_TYPE_MAC97972, .name = "MAC97972" }, + { .val = KMIP_KEY_ROLE_TYPE_MAC97973, .name = "MAC97973" }, + { .val = KMIP_KEY_ROLE_TYPE_MAC97974, .name = "MAC97974" }, + { .val = KMIP_KEY_ROLE_TYPE_MAC97975, .name = "MAC97975" }, + { .val = KMIP_KEY_ROLE_TYPE_ZPK, .name = "ZPK" }, + { .val = KMIP_KEY_ROLE_TYPE_PVKIBM, .name = "PVKIBM" }, + { .val = KMIP_KEY_ROLE_TYPE_PVKPVV, .name = "PVKPVV" }, + { .val = KMIP_KEY_ROLE_TYPE_PVKOTH, .name = "PVKOTH" }, + { .val = KMIP_KEY_ROLE_TYPE_DUKPT, .name = "DUKPT" }, + { .val = KMIP_KEY_ROLE_TYPE_IV, .name = "IV" }, + { .val = KMIP_KEY_ROLE_TYPE_TRKBK, .name = "TRKBK" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_sinature_algos[] = { + { .val = KMIP_SIGNATURE_ALGO_MD2_WITH_RSA_ENCRYPTION, + .name = "MD2WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_MD5_WITH_RSA_ENCRYPTION, + .name = "MD5WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_SHA_1_WITH_RSA_ENCRYPTION, + .name = "SHA_1WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_SHA_224_WITH_RSA_ENCRYPTION, + .name = "SHA_244WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_SHA_256_WITH_RSA_ENCRYPTION, + .name = "SHA_256WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_SHA_384_WITH_RSA_ENCRYPTION, + .name = "SHA_384WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_SHA_512_WITH_RSA_ENCRYPTION, + .name = "SHA_512WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_RSASSA_PSS, .name = "RSASSA_PSS" }, + { .val = KMIP_SIGNATURE_ALGO_DSA_WITH_SHA_1, .name = "DSAWithSHA_1" }, + { .val = KMIP_SIGNATURE_ALGO_DSA_WITH_SHA_244, + .name = "DSAWithSHA224" }, + { .val = KMIP_SIGNATURE_ALGO_DSA_WITH_SHA_256, + .name = "DSAWithSHA256" }, + { .val = KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_1, + .name = "ECDSAWithSHA_1" }, + { .val = KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_224, + .name = "ECDSAWithSHA224" }, + { .val = KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_256, + .name = "ECDSAWithSHA256" }, + { .val = KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_384, + .name = "ECDSAWithSHA384" }, + { .val = KMIP_SIGNATURE_ALGO_ECDSA_WITH_SHA_512, + .name = "ECDSAWithSHA512" }, + { .val = KMIP_SIGNATURE_ALGO_SHA3_256_WITH_RSA_ENCRYPTION, + .name = "SHA3_256WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_SHA3_385_WITH_RSA_ENCRYPTION, + .name = "SHA3_384WithRSAEncryption" }, + { .val = KMIP_SIGNATURE_ALGO_SHA3_512_WITH_RSA_ENCRYPTION, + .name = "SHA3_512WithRSAEncryption" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_mask_generators[] = { + { .val = KMIP_MASK_GENERATOR_MGF1, .name = "MGF1" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_encoding_options[] = { + { .val = KMIP_ENCODING_OPTION_NO, .name = "NoEncoding" }, + { .val = KMIP_ENCODING_OPTION_TTLV, .name = "TTLVEncoding" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_recommended_cuurves[] = { + { .val = KMIP_REC_CURVE_P_192, .name = "P192" }, + { .val = KMIP_REC_CURVE_K_163, .name = "K163" }, + { .val = KMIP_REC_CURVE_B_163, .name = "B163" }, + { .val = KMIP_REC_CURVE_P_224, .name = "P224" }, + { .val = KMIP_REC_CURVE_K_223, .name = "K223" }, + { .val = KMIP_REC_CURVE_B_223, .name = "B223" }, + { .val = KMIP_REC_CURVE_P_256, .name = "P256" }, + { .val = KMIP_REC_CURVE_K_283, .name = "K283" }, + { .val = KMIP_REC_CURVE_B_283, .name = "B283" }, + { .val = KMIP_REC_CURVE_P_384, .name = "P384" }, + { .val = KMIP_REC_CURVE_K_409, .name = "K409" }, + { .val = KMIP_REC_CURVE_B_409, .name = "B409" }, + { .val = KMIP_REC_CURVE_P_521, .name = "P521" }, + { .val = KMIP_REC_CURVE_K_571, .name = "K571" }, + { .val = KMIP_REC_CURVE_B_571, .name = "B571" }, + { .val = KMIP_REC_CURVE_SECP112R1, .name = "Secp112r1" }, + { .val = KMIP_REC_CURVE_SECP112R2, .name = "Secp112r2" }, + { .val = KMIP_REC_CURVE_SECP128R1, .name = "Secp128r1" }, + { .val = KMIP_REC_CURVE_SECP128R2, .name = "Secp128r2" }, + { .val = KMIP_REC_CURVE_SECP160K1, .name = "Secp160k1" }, + { .val = KMIP_REC_CURVE_SECP160R1, .name = "Secp160r1" }, + { .val = KMIP_REC_CURVE_SECP160R2, .name = "Secp160r2" }, + { .val = KMIP_REC_CURVE_SECP192K1, .name = "Secp192k1" }, + { .val = KMIP_REC_CURVE_SECP224K1, .name = "Secp224k1" }, + { .val = KMIP_REC_CURVE_SECP256K1, .name = "Secp256k1" }, + { .val = KMIP_REC_CURVE_SECT113R1, .name = "Sect113r1" }, + { .val = KMIP_REC_CURVE_SECT113R2, .name = "Sect113r2" }, + { .val = KMIP_REC_CURVE_SECT131R1, .name = "Sect131r1" }, + { .val = KMIP_REC_CURVE_SECT131R2, .name = "Sect131r2" }, + { .val = KMIP_REC_CURVE_SECT163R1, .name = "Sect163r1" }, + { .val = KMIP_REC_CURVE_SECT193R1, .name = "Sect193r1" }, + { .val = KMIP_REC_CURVE_SECT193R2, .name = "Sect193r2" }, + { .val = KMIP_REC_CURVE_SECT239K1, .name = "Sect239k1" }, + { .val = KMIP_REC_CURVE_ANSIX9P192V2, .name = "Ansix9p192v2" }, + { .val = KMIP_REC_CURVE_ANSIX9P192V3, .name = "Ansix9p192v3" }, + { .val = KMIP_REC_CURVE_ANSIX9P239V1, .name = "Ansix9p239v1" }, + { .val = KMIP_REC_CURVE_ANSIX9P239V2, .name = "Ansix9p239v2" }, + { .val = KMIP_REC_CURVE_ANSIX9P239V3, .name = "Ansix9p239v3" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB163V1, .name = "Ansix9c2pnb163v1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB163V2, .name = "Ansix9c2pnb163v2" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB163V3, .name = "Ansix9c2pnb163v3" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB176V1, .name = "Ansix9c2pnb176v1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB191V1, .name = "Ansix9c2tnb191v1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB191V2, .name = "Ansix9c2tnb191v2" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB191V3, .name = "Ansix9c2tnb191v3" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB208W1, .name = "Ansix9c2pnb208w1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB239V1, .name = "Ansix9c2tnb239v1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB239V2, .name = "Ansix9c2tnb239v2" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB239V3, .name = "Ansix9c2tnb239v3" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB272W1, .name = "Ansix9c2pnb272w1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB304W1, .name = "Ansix9c2pnb304w1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB359V1, .name = "Ansix9c2tnb359v1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2PNB368W1, .name = "Ansix9c2pnb368w1" }, + { .val = KMIP_REC_CURVE_ANSIX9C2TNB431R1, .name = "Ansix9c2tnb431r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP160R1, .name = "Brainpoolp160r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP160T1, .name = "Brainpoolp160t1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP192R1, .name = "Brainpoolp192r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP192T1, .name = "Brainpoolp192t1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP224R1, .name = "Brainpoolp224r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP224T1, .name = "Brainpoolp224t1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP256R1, .name = "Brainpoolp256r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP256T1, .name = "Brainpoolp256t1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP320R1, .name = "Brainpoolp320r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP320T1, .name = "Brainpoolp320t1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP384R1, .name = "Brainpoolp384r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP384T1, .name = "Brainpoolp384t1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP512R1, .name = "Brainpoolp512r1" }, + { .val = KMIP_REC_CURVE_BRAINPOOLP512T1, .name = "Brainpoolp512t1" }, + { .val = KMIP_REC_CURVE_CURVE25519, .name = "Curve25519" }, + { .val = KMIP_REC_CURVE_CURVE448, .name = "Curve448" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_protection_levels[] = { + { .val = KMIP_PROTECTION_LEVEL_HIGH, .name = "High" }, + { .val = KMIP_PROTECTION_LEVEL_LOW, .name = "Low" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_key_value_location_types[] = { + { .val = KMIP_KEY_VAL_LOC_TYPE_UNINTERPRETED_TEXT_STRING, + .name = "UninterpretedTextString" }, + { .val = KMIP_KEY_VAL_LOC_TYPE_URI, .name = "URI" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_link_types[] = { + { .val = KMIP_LINK_TYPE_CERTIFICATE, .name = "CertificateLink" }, + { .val = KMIP_LINK_TYPE_PUBLIC_KEY, .name = "PublicKeyLink" }, + { .val = KMIP_LINK_TYPE_PRIVATE_KEY, .name = "PrivateKeyLink" }, + { .val = KMIP_LINK_TYPE_DERIVATION_BASE_OBJECT, + .name = "DerivationBaseObjectLink" }, + { .val = KMIP_LINK_TYPE_DERIVED_KEY, .name = "DerivedKeyLink" }, + { .val = KMIP_LINK_TYPE_REPLACEMENT_OBJECT, + .name = "ReplacementObjectLink" }, + { .val = KMIP_LINK_TYPE_REPLACED_OBJECT, .name = "ReplacedObjectLink" }, + { .val = KMIP_LINK_TYPE_PARENT, .name = "ParentLink" }, + { .val = KMIP_LINK_TYPE_CHILD, .name = "ChildLink" }, + { .val = KMIP_LINK_TYPE_PREVIOUS, .name = "PreviousLink" }, + { .val = KMIP_LINK_TYPE_NEXT, .name = "NextLink" }, + { .val = KMIP_LINK_TYPE_PKCS_12_CERTIFICATE, + .name = "PKCS_12CertificateLink" }, + { .val = KMIP_LINK_TYPE_PKCS_12_PASSWORD, + .name = "PKCS_12PasswordLink" }, + { .val = KMIP_LINK_TYPE_WRAPPING_KEY, .name = "WrappingKeyLink" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_client_registration_methods[] = { + { .val = KMIP_CLIENT_REG_METH_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_CLIENT_REG_METH_SERVER_PRE_GENERATED, + .name = "ServerPreGenerated" }, + { .val = KMIP_CLIENT_REG_METH_SERVER_ON_DEMAND, + .name = "ServerOnDemand" }, + { .val = KMIP_CLIENT_REG_METH_CLIENT_GENERATED, + .name = "ClientGenerated" }, + { .val = KMIP_CLIENT_REG_METH_CLIENT_REGISTERED, + .name = "ClientRegistered" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_rng_algorithms[] = { + { .val = KMIP_RNG_ALGO_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_RNG_ALGO_FIPS_186_2, .name = "FIPS186_2" }, + { .val = KMIP_RNG_ALGO_DRBG, .name = "DRBG" }, + { .val = KMIP_RNG_ALGO_NRBG, .name = "NRBG" }, + { .val = KMIP_RNG_ALGO_ANSI_X9_31, .name = "ANSIX9_31" }, + { .val = KMIP_RNG_ALGO_ANSI_X9_62, .name = "ANSIX9_62" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_drbg_algorithms[] = { + { .val = KMIP_DRBG_ALGO_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_DRBG_ALGO_DUAL_EC, .name = "Dual_EC" }, + { .val = KMIP_DRBG_ALGO_HASH, .name = "Hash" }, + { .val = KMIP_DRBG_ALGO_HMAC, .name = "HMAC" }, + { .val = KMIP_DRBG_ALGO_CTR, .name = "CTR" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_fips186_variations[] = { + { .val = KMIP_FIPS186_VARI_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_FIPS186_VARI_GP_X_ORIGINAL, .name = "GPxOriginal" }, + { .val = KMIP_FIPS186_VARI_GP_X_CHANGE_NOTICE, + .name = "GPxChangeNotice" }, + { .val = KMIP_FIPS186_VARI_X_ORIGINAL, .name = "XOriginal" }, + { .val = KMIP_FIPS186_VARI_X_CHANGE_NOTICE, .name = "XChangeNotice" }, + { .val = KMIP_FIPS186_VARI_K_ORIGINAL, .name = "KOriginal" }, + { .val = KMIP_FIPS186_VARI_K_CHANGE_NOTICE, .name = "KChangeNotice" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_validation_authority_types[] = { + { .val = KMIP_VALIDATION_AUTH_TYPE_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_VALIDATION_AUTH_TYPE_NIST_CMVP, .name = "NISTCMVP" }, + { .val = KMIP_VALIDATION_AUTH_TYPE_COMMON_CRITERIA, + .name = "CommonCriteria" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_validation_types[] = { + { .val = KMIP_VALIDATION_TYPE_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_VALIDATION_TYPE_HARDWARE, .name = "Hardware" }, + { .val = KMIP_VALIDATION_TYPE_SOFTWARE, .name = "Software" }, + { .val = KMIP_VALIDATION_TYPE_FIRMWARE, .name = "Firmware" }, + { .val = KMIP_VALIDATION_TYPE_HYBRID, .name = "Hybrid" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_unwrap_modes[] = { + { .val = KMIP_UNWRAP_MODE_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_UNWRAP_MODE_PROCESSED, .name = "Processed" }, + { .val = KMIP_UNWRAP_MODE_NOT_PROCESSED, .name = "NotProcessed" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_destroy_actions[] = { + { .val = KMIP_DESTROY_ACTION_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_DESTROY_ACTION_KEY_MATERIAL_DELETED, + .name = "KeyMaterialDeleted" }, + { .val = KMIP_DESTROY_ACTION_KEY_MATERIAL_SHREDDED, + .name = "KeyMaterialShredded" }, + { .val = KMIP_DESTROY_ACTION_META_DATA_DELETED, + .name = "MetaDataDeleted" }, + { .val = KMIP_DESTROY_ACTION_META_DATA_SHREDDED, + .name = "MetaDataShredded" }, + { .val = KMIP_DESTROY_ACTION_DELETED, .name = "Deleted" }, + { .val = KMIP_DESTROY_ACTION_SHREDDED, .name = "Shredded" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_shredding_algorithms[] = { + { .val = KMIP_SHREDDING_ALGO_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_SHREDDING_ALGO_CRYPTOGRAPHIC, .name = "Cryptographic" }, + { .val = KMIP_SHREDDING_ALGO_UNSUPPORTED, .name = "Unsupported" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_rng_modes[] = { + { .val = KMIP_RNG_MODE_UNSPECIFIED, .name = "Unspecified" }, + { .val = KMIP_RNG_MODE_SHARED_INSTANTIATION, + .name = "SharedInstantiation" }, + { .val = KMIP_RNG_MODE_NON_SHARED_INSTANCIATION, + .name = "NonSharedInstantiation" }, + { .val = 0, .name = NULL }, +}; + +static const struct kmip_enum kmip_profile_names[] = { + { .val = KMIP_PROFILE_BASELINE_SERVER_BASIC_KMIP_V1_2, + .name = "BaselineServerBasicKMIPV1_2" }, + { .val = KMIP_PROFILE_BASELINE_SERVER_TLS_V1_2_KMIP_V1_2, + .name = "BaselineServerTLSV1_2KMIPV1_2" }, + { .val = KMIP_PROFILE_BASELINE_CLIENT_BASIC_KMIP_V1_2, + .name = "BaselineClientBasicKMIPV1_2" }, + { .val = KMIP_PROFILE_BASELINE_CLIENT_TLS_V1_2_KMIP_V1_2, + .name = "BaselineClientTLSV1_2KMIPV1_2" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_BASIC_KMIP_V1_2, + .name = "CompleteServerBasicKMIPV1_2" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2_KMIP_V1_2, + .name = "CompleteServerTLSV1_2KMIPV1_2" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_0, + .name = "TapeLibraryClientKMIPV1_0" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_1, + .name = "TapeLibraryClientKMIPV1_1" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_2, + .name = "TapeLibraryClientKMIPV1_2" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_0, + .name = "TapeLibraryServerKMIPV1_0" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_1, + .name = "TapeLibraryServerKMIPV1_1" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_2, + .name = "TapeLibraryServerKMIPV1_2" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_0, + .name = "SymmetricKeyLifecycleClientKMIPV1_0" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_1, + .name = "SymmetricKeyLifecycleClientKMIPV1_1" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_2, + .name = "SymmetricKeyLifecycleClientKMIPV1_2" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_0, + .name = "SymmetricKeyLifecycleServerKMIPV1_0" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_1, + .name = "SymmetricKeyLifecycleServerKMIPV1_1" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_2, + .name = "SymmetricKeyLifecycleServerKMIPV1_2" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_0, + .name = "AsymmetricKeyLifecycleClientKMIPV1_0" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_1, + .name = "AsymmetricKeyLifecycleClientKMIPV1_1" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_2, + .name = "AsymmetricKeyLifecycleClientKMIPV1_2" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_0, + .name = "AsymmetricKeyLifecycleServerKMIPV1_0" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_1, + .name = "AsymmetricKeyLifecycleServerKMIPV1_1" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_2, + .name = "AsymmetricKeyLifecycleServerKMIPV1_2" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT_KMIP_V1_2, + .name = "BasicCryptographicClientKMIPV1_2" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER_KMIP_V1_2, + .name = "BasicCryptographicServerKMIPV1_2" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT_KMIP_V1_2, + .name = "AdvancedCryptographicClientKMIPV1_2" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER_KMIP_V1_2, + .name = "AdvancedCryptographicServerKMIPV1_2" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT_KMIP_V1_2, + .name = "RNGCryptographicClientKMIPV1_2" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER_KMIP_V1_2, + .name = "RNGCryptographicServerKMIPV1_2" }, + { .val = KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_0, + .name = "BasicSymmetricKeyFoundryClientKMIPV1_0" }, + { .val = KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_0, + .name = "IntermediateSymmetricKeyFoundryClientKMIPV1_0" }, + { .val = KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_0, + .name = "AdvancedSymmetricKeyFoundryClientKMIPV1_0" }, + { .val = KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_1, + .name = "BasicSymmetricKeyFoundryClientKMIPV1_1" }, + { .val = KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_1, + .name = "IntermediateSymmetricKeyFoundryClientKMIPV1_1" }, + { .val = KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_1, + .name = "AdvancedSymmetricKeyFoundryClientKMIPV1_1" }, + { .val = KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_2, + .name = "BasicSymmetricKeyFoundryClientKMIPV1_2" }, + { .val = KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_2, + .name = "IntermediateSymmetricKeyFoundryClientKMIPV1_2" }, + { .val = KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_2, + .name = "AdvancedSymmetricKeyFoundryClientKMIPV1_2" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_0, + .name = "SymmetricKeyFoundryServerKMIPV1_0" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_1, + .name = "SymmetricKeyFoundryServerKMIPV1_1" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_2, + .name = "SymmetricKeyFoundryServerKMIPV1_2" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_0, + .name = "OpaqueManagedObjectStoreClientKMIPV1_0" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_1, + .name = "OpaqueManagedObjectStoreClientKMIPV1_1" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_2, + .name = "OpaqueManagedObjectStoreClientKMIPV1_2" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_0, + .name = "OpaqueManagedObjectStoreServerKMIPV1_0" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_1, + .name = "OpaqueManagedObjectStoreServerKMIPV1_1" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_2, + .name = "OpaqueManagedObjectStoreServerKMIPV1_2" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_0, + .name = "SuiteBMinLOS_128ClientKMIPV1_0" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_1, + .name = "SuiteBMinLOS_128ClientKMIPV1_1" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_2, + .name = "SuiteBMinLOS_128ClientKMIPV1_2" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_0, + .name = "SuiteBMinLOS_128ServerKMIPV1_0" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_1, + .name = "SuiteBMinLOS_128ServerKMIPV1_1" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_2, + .name = "SuiteBMinLOS_128ServerKMIPV1_2" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_0, + .name = "SuiteBMinLOS_192ClientKMIPV1_0" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_1, + .name = "SuiteBMinLOS_192ClientKMIPV1_1" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_2, + .name = "SuiteBMinLOS_192ClientKMIPV1_2" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_0, + .name = "SuiteBMinLOS_192ServerKMIPV1_0" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_1, + .name = "SuiteBMinLOS_192ServerKMIPV1_1" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_2, + .name = "SuiteBMinLOS_192ServerKMIPV1_2" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_0, + .name = "StorageArrayWithSelfEncryptingDriveClientKMIPV1_0" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_1, + .name = "StorageArrayWithSelfEncryptingDriveClientKMIPV1_1" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_2, + .name = "StorageArrayWithSelfEncryptingDriveClientKMIPV1_2" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_0, + .name = "StorageArrayWithSelfEncryptingDriveServerKMIPV1_0" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_1, + .name = "StorageArrayWithSelfEncryptingDriveServerKMIPV1_1" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_2, + .name = "StorageArrayWithSelfEncryptingDriveServerKMIPV1_2" }, + { .val = KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_0, + .name = "HTTPSClientKMIPV1_0" }, + { .val = KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_1, + .name = "HTTPSClientKMIPV1_1" }, + { .val = KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_2, + .name = "HTTPSClientKMIPV1_2" }, + { .val = KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_0, + .name = "HTTPSServerKMIPV1_0" }, + { .val = KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_1, + .name = "HTTPSServerKMIPV1_1" }, + { .val = KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_2, + .name = "HTTPSServerKMIPV1_2" }, + { .val = KMIP_PROFILE_JSON_CLIENT_KMIP_V1_0, + .name = "JSONClientKMIPV1_0" }, + { .val = KMIP_PROFILE_JSON_CLIENT_KMIP_V1_1, + .name = "JSONClientKMIPV1_1" }, + { .val = KMIP_PROFILE_JSON_CLIENT_KMIP_V1_2, + .name = "JSONClientKMIPV1_2" }, + { .val = KMIP_PROFILE_JSON_SERVER_KMIP_V1_0, + .name = "JSONServerKMIPV1_0" }, + { .val = KMIP_PROFILE_JSON_SERVER_KMIP_V1_1, + .name = "JSONServerKMIPV1_1" }, + { .val = KMIP_PROFILE_JSON_SERVER_KMIP_V1_2, + .name = "JSONServerKMIPV1_2" }, + { .val = KMIP_PROFILE_XML_CLIENT_KMIP_V1_0, + .name = "XMLClientKMIPV1_0" }, + { .val = KMIP_PROFILE_XML_CLIENT_KMIP_V1_1, + .name = "XMLClientKMIPV1_1" }, + { .val = KMIP_PROFILE_XML_CLIENT_KMIP_V1_2, + .name = "XMLClientKMIPV1_2" }, + { .val = KMIP_PROFILE_XML_SERVER_KMIP_V1_0, + .name = "XMLServerKMIPV1_0" }, + { .val = KMIP_PROFILE_XML_SERVER_KMIP_V1_1, + .name = "XMLServerKMIPV1_1" }, + { .val = KMIP_PROFILE_XML_SERVER_KMIP_V1_2, + .name = "XMLServerKMIPV1_2" }, + { .val = KMIP_PROFILE_BASELINE_SERVER_BASIC_KMIP_V1_3, + .name = "BaselineServerBasicKMIPV1_3" }, + { .val = KMIP_PROFILE_BASELINE_SERVER_TLS_V1_2_KMIP_V1_3, + .name = "BaselineServerTLSV1_2KMIPV1_3" }, + { .val = KMIP_PROFILE_BASELINE_CLIENT_BASIC_KMIP_V1_3, + .name = "BaselineClientBasicKMIPV1_3" }, + { .val = KMIP_PROFILE_BASELINE_CLIENT_TLS_V1_2_KMIP_V1_3, + .name = "BaselineClientTLSV1_2KMIPV1_3" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_BASIC_KMIP_V1_3, + .name = "CompleteServerBasicKMIPV1_3" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2_KMIP_V1_3, + .name = "CompleteServerTLSV1_2KMIPV1_3" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_3, + .name = "TapeLibraryClientKMIPV1_3" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_3, + .name = "TapeLibraryServerKMIPV1_3" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_3, + .name = "SymmetricKeyLifecycleClientKMIPV1_3" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_3, + .name = "SymmetricKeyLifecycleServerKMIPV1_3" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_3, + .name = "AsymmetricKeyLifecycleClientKMIPV1_3" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_3, + .name = "AsymmetricKeyLifecycleServerKMIPV1_3" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT_KMIP_V1_3, + .name = "BasicCryptographicClientKMIPV1_3" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER_KMIP_V1_3, + .name = "BasicCryptographicServerKMIPV1_3" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT_KMIP_V1_3, + .name = "AdvancedCryptographicClientKMIPV1_3" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER_KMIP_V1_3, + .name = "AdvancedCryptographicServerKMIPV1_3" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT_KMIP_V1_3, + .name = "RNGCryptographicClientKMIPV1_3" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER_KMIP_V1_3, + .name = "RNGCryptographicServerKMIPV1_3" }, + { .val = KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_3, + .name = "BasicSymmetricKeyFoundryClientKMIPV1_3" }, + { .val = KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_3, + .name = "IntermediateSymmetricKeyFoundryClientKMIPV1_3" }, + { .val = KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_3, + .name = "AdvancedSymmetricKeyFoundryClientKMIPV1_3" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_3, + .name = "SymmetricKeyFoundryServerKMIPV1_3" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_3, + .name = "OpaqueManagedObjectStoreClientKMIPV1_3" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_3, + .name = "OpaqueManagedObjectStoreServerKMIPV1_3" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_3, + .name = "SuiteBMinLOS_128ClientKMIPV1_3" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_3, + .name = "SuiteBMinLOS_128ServerKMIPV1_3" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_3, + .name = "SuiteBMinLOS_192ClientKMIPV1_3" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_3, + .name = "SuiteBMinLOS_192ServerKMIPV1_3" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_3, + .name = "StorageArrayWithSelfEncryptingDriveClientKMIPV1_3" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_3, + .name = "StorageArrayWithSelfEncryptingDriveServerKMIPV1_3" }, + { .val = KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_3, + .name = "HTTPSClientKMIPV1_3" }, + { .val = KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_3, + .name = "HTTPSServerKMIPV1_3" }, + { .val = KMIP_PROFILE_JSON_CLIENT_KMIP_V1_3, + .name = "JSONClientKMIPV1_3" }, + { .val = KMIP_PROFILE_JSON_SERVER_KMIP_V1_3, + .name = "JSONServerKMIPV1_3" }, + { .val = KMIP_PROFILE_XML_CLIENT_KMIP_V1_3, + .name = "XMLClientKMIPV1_3" }, + { .val = KMIP_PROFILE_XML_SERVER_KMIP_V1_3, + .name = "XMLServerKMIPV1_3" }, + { .val = KMIP_PROFILE_BASELINE_SERVER_BASIC_KMIP_V1_4, + .name = "BaselineServerBasicKMIPV1_4" }, + { .val = KMIP_PROFILE_BASELINE_SERVER_TLS_V1_2_KMIP_V1_4, + .name = "BaselineServerTLSV1_2KMIPV1_4" }, + { .val = KMIP_PROFILE_BASELINE_CLIENT_BASIC_KMIP_V1_4, + .name = "BaselineClientBasicKMIPV1_4" }, + { .val = KMIP_PROFILE_BASELINE_CLIENT_TLS_V1_2_KMIP_V1_4, + .name = "BaselineClientTLSV1_2KMIPV1_4" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_BASIC_KMIP_V1_4, + .name = "CompleteServerBasicKMIPV1_4" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2_KMIP_V1_4, + .name = "CompleteServerTLSV1_2KMIPV1_4" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_CLIENT_KMIP_V1_4, + .name = "TapeLibraryClientKMIPV1_4" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_SERVER_KMIP_V1_4, + .name = "TapeLibraryServerKMIPV1_4" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_4, + .name = "SymmetricKeyLifecycleClientKMIPV1_4" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_4, + .name = "SymmetricKeyLifecycleServerKMIPV1_4" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT_KMIP_V1_4, + .name = "AsymmetricKeyLifecycleClientKMIPV1_4" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER_KMIP_V1_4, + .name = "AsymmetricKeyLifecycleServerKMIPV1_4" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT_KMIP_V1_4, + .name = "BasicCryptographicClientKMIPV1_4" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER_KMIP_V1_4, + .name = "BasicCryptographicServerKMIPV1_4" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT_KMIP_V1_4, + .name = "AdvancedCryptographicClientKMIPV1_4" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER_KMIP_V1_4, + .name = "AdvancedCryptographicServerKMIPV1_4" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT_KMIP_V1_4, + .name = "RNGCryptographicClientKMIPV1_4" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER_KMIP_V1_4, + .name = "RNGCryptographicServerKMIPV1_4" }, + { .val = KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_4, + .name = "BasicSymmetricKeyFoundryClientKMIPV1_4" }, + { .val = KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_4, + .name = "IntermediateSymmetricKeyFoundryClientKMIPV1_4" }, + { .val = KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT_KMIP_V1_4, + .name = "AdvancedSymmetricKeyFoundryClientKMIPV1_4" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER_KMIP_V1_4, + .name = "SymmetricKeyFoundryServerKMIPV1_4" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT_KMIP_V1_4, + .name = "OpaqueManagedObjectStoreClientKMIPV1_4" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER_KMIP_V1_4, + .name = "OpaqueManagedObjectStoreServerKMIPV1_4" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_CLIENT_KMIP_V1_4, + .name = "SuiteBMinLOS_128ClientKMIPV1_4" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_128_SERVER_KMIP_V1_4, + .name = "SuiteBMinLOS_128ServerKMIPV1_4" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_CLIENT_KMIP_V1_4, + .name = "SuiteBMinLOS_192ClientKMIPV1_4" }, + { .val = KMIP_PROFILE_SUITE_B_MINLOS_192_SERVER_KMIP_V1_4, + .name = "SuiteBMinLOS_192ServerKMIPV1_4" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT_KMIP_V1_4, + .name = "StorageArrayWithSelfEncryptingDriveClientKMIPV1_4" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER_KMIP_V1_4, + .name = "StorageArrayWithSelfEncryptingDriveServerKMIPV1_4" }, + { .val = KMIP_PROFILE_HTTPS_CLIENT_KMIP_V1_4, + .name = "HTTPSClientKMIPV1_4" }, + { .val = KMIP_PROFILE_HTTPS_SERVER_KMIP_V1_4, + .name = "HTTPSServerKMIPV1_4" }, + { .val = KMIP_PROFILE_JSON_CLIENT_KMIP_V1_4, + .name = "JSONClientKMIPV1_4" }, + { .val = KMIP_PROFILE_JSON_SERVER_KMIP_V1_4, + .name = "JSONServerKMIPV1_4" }, + { .val = KMIP_PROFILE_XML_CLIENT_KMIP_V1_4, + .name = "XMLClientKMIPV1_4" }, + { .val = KMIP_PROFILE_XML_SERVER_KMIP_V1_4, + .name = "XMLServerKMIPV1_4" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_BASIC, + .name = "CompleteServerBasic" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER_TLS_V1_2, + .name = "CompleteServerTLSV1_2" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_CLIENT, + .name = "TapeLibraryClient" }, + { .val = KMIP_PROFILE_TAPE_LIBRARY_SERVER, + .name = "TapeLibraryServer" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_CLIENT, + .name = "SymmetricKeyLifecycleClient" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_LIFECYCLE_SERVER, + .name = "SymmetricKeyLifecycleServer" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_CLIENT, + .name = "AsymmetricKeyLifecycleClient" }, + { .val = KMIP_PROFILE_ASYMMETRIC_KEY_LIFECYCLE_SERVER, + .name = "AsymmetricKeyLifecycleServer" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_CLIENT, + .name = "BasicCryptographicClient" }, + { .val = KMIP_PROFILE_BASIC_CRYPTOGRAPHIC_SERVER, + .name = "BasicCryptographicServer" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_CLIENT, + .name = "AdvancedCryptographicClient" }, + { .val = KMIP_PROFILE_ADVANCED_CRYPTOGRAPHIC_SERVER, + .name = "AdvancedCryptographicServer" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_CLIENT, + .name = "RNGCryptographicClient" }, + { .val = KMIP_PROFILE_RNG_CRYPTOGRAPHIC_SERVER, + .name = "RNGCryptographicServer" }, + { .val = KMIP_PROFILE_BASIC_SYMMETRIC_KEY_FOUNDRY_CLIENT, + .name = "BasicSymmetricKeyFoundryClient" }, + { .val = KMIP_PROFILE_INTERMEDIATE_SYMMETRIC_KEY_FOUNDRY_CLIENT, + .name = "IntermediateSymmetricKeyFoundryClient" }, + { .val = KMIP_PROFILE_ADVANCED_SYMMETRIC_KEY_FOUNDRY_CLIENT, + .name = "AdvancedSymmetricKeyFoundryClient" }, + { .val = KMIP_PROFILE_SYMMETRIC_KEY_FOUNDRY_SERVER, + .name = "SymmetricKeyFoundryServer" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_CLIENT, + .name = "OpaqueManagedObjectStoreClient" }, + { .val = KMIP_PROFILE_OPAQUE_MANAGED_OBJECT_STORE_SERVER, + .name = "OpaqueManagedObjectStoreServer" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_CLIENT, + .name = "StorageArrayWithSelfEncryptingDriveClient" }, + { .val = KMIP_PROFILE_STORAGE_ARRAY_WITH_SELF_ENCRYPTING_DRIVE_SERVER, + .name = "StorageArrayWithSelfEncryptingDriveServer" }, + { .val = KMIP_PROFILE_HTTPS_CLIENT, + .name = "HTTPSClient" }, + { .val = KMIP_PROFILE_HTTPS_SERVER, + .name = "HTTPSServer" }, + { .val = KMIP_PROFILE_JSON_CLIENT, + .name = "JSONClient" }, + { .val = KMIP_PROFILE_JSON_SERVER, + .name = "JSONServer" }, + { .val = KMIP_PROFILE_XML_CLIENT, + .name = "XMLClient" }, + { .val = KMIP_PROFILE_XML_SERVER, + .name = "XMLServer" }, + { .val = KMIP_PROFILE_AES_XTS_CLIENT, + .name = "AESXTSClient" }, + { .val = KMIP_PROFILE_AES_XTS_SERVER, + .name = "AESXTSServer" }, + { .val = KMIP_PROFILE_QUANTUM_SAFE_CLIENT, + .name = "QuantumSafeClient" }, + { .val = KMIP_PROFILE_QUANTUM_SAFE_SERVER, + .name = "QuantumSafeServer" }, + { .val = KMIP_PROFILE_PKCS_11_CLIENT, + .name = "PKCS_11Client" }, + { .val = KMIP_PROFILE_PKCS_11_SERVER, + .name = "PKCS_11Server" }, + { .val = KMIP_PROFILE_BASELINE_CLIENT, + .name = "BaselineClient" }, + { .val = KMIP_PROFILE_BASELINE_SERVER, + .name = "BaselineServer" }, + { .val = KMIP_PROFILE_COMPLETE_SERVER, + .name = "CompleteServer" }, + { .val = 0, .name = NULL }, +}; + +struct kmip_enum_info { + enum kmip_tag tag; + const struct kmip_enum *enum_info; + bool is_mask; +}; + +static const struct kmip_enum_info enum_info[] = { + { .tag = KMIP_TAG_ATTRIBUTE_REFERENCE, .enum_info = kmip_tags, + .is_mask = false }, + { .tag = KMIP_TAG_OPERATION, .enum_info = kmip_operations, + .is_mask = false }, + { .tag = KMIP_TAG_BATCH_ERROR_CONTINUATION_OPTION, + .enum_info = kmip_batch_error_cont_options, .is_mask = false }, + { .tag = KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK, + .enum_info = kmip_crypto_usage_masks, .is_mask = true }, + { .tag = KMIP_TAG_RESULT_STATUS, + .enum_info = kmip_result_statuses, .is_mask = false }, + { .tag = KMIP_TAG_RESULT_REASON, + .enum_info = kmip_result_reasons, .is_mask = false }, + { .tag = KMIP_TAG_QUERY_FUNCTION, + .enum_info = kmip_query_functions, .is_mask = false }, + { .tag = KMIP_TAG_NAME_TYPE, + .enum_info = kmip_name_types, .is_mask = false }, + { .tag = KMIP_TAG_ALTERNATE_NAME_TYPE, + .enum_info = kmip_alternate_name_types, .is_mask = false }, + { .tag = KMIP_TAG_UNIQUE_IDENTIFIER, + .enum_info = kmip_unique_identifiers, .is_mask = false }, + { .tag = KMIP_TAG_OBJECT_TYPE, + .enum_info = kmip_object_types, .is_mask = false }, + { .tag = KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, + .enum_info = kmip_crypto_algos, .is_mask = false }, + { .tag = KMIP_TAG_CERTIFICATE_TYPE, + .enum_info = kmip_certificate_types, .is_mask = false }, + { .tag = KMIP_TAG_STATE, + .enum_info = kmip_states, .is_mask = false }, + { .tag = KMIP_TAG_PROTECTION_STORAGE_MASK, + .enum_info = kmip_protection_storage_masks, .is_mask = true }, + { .tag = KMIP_TAG_REVOCATION_REASON_CODE, + .enum_info = kmip_revoke_reasons, .is_mask = false }, + { .tag = KMIP_TAG_OBJECT_GROUP_MEMBER, + .enum_info = kmip_object_group_members, .is_mask = false }, + { .tag = KMIP_TAG_STORAGE_STATUS_MASK, + .enum_info = kmip_storage_status_masks, .is_mask = true }, + { .tag = KMIP_TAG_KEY_FORMAT_TYPE, + .enum_info = kmip_key_format_types, .is_mask = false }, + { .tag = KMIP_TAG_KEY_COMPRESSION_TYPE, + .enum_info = kmip_key_compression_types, .is_mask = false }, + { .tag = KMIP_TAG_WRAPPING_METHOD, + .enum_info = kmip_wrapping_methods, .is_mask = false }, + { .tag = KMIP_TAG_KEY_WRAP_TYPE, + .enum_info = kmip_key_wrap_types, .is_mask = false }, + { .tag = KMIP_TAG_BLOCK_CIPHER_MODE, + .enum_info = kmip_block_cipher_modes, .is_mask = false }, + { .tag = KMIP_TAG_PADDING_METHOD, + .enum_info = kmip_padding_methods, .is_mask = false }, + { .tag = KMIP_TAG_HASHING_ALGORITHM, + .enum_info = kmip_hashing_algos, .is_mask = false }, + { .tag = KMIP_TAG_MASK_GENERATOR_HASHING_ALGORITHM, + .enum_info = kmip_hashing_algos, .is_mask = false }, + { .tag = KMIP_TAG_KEY_ROLE_TYPE, + .enum_info = kmip_key_role_types, .is_mask = false }, + { .tag = KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM, + .enum_info = kmip_sinature_algos, .is_mask = false }, + { .tag = KMIP_TAG_MASK_GENERATOR, + .enum_info = kmip_mask_generators, .is_mask = false }, + { .tag = KMIP_TAG_ENCODING_OPTION, + .enum_info = kmip_encoding_options, .is_mask = false }, + { .tag = KMIP_TAG_RECOMMENDED_CURVE, + .enum_info = kmip_recommended_cuurves, .is_mask = false }, + { .tag = KMIP_TAG_PROTECTION_LEVEL, + .enum_info = kmip_protection_levels, .is_mask = false }, + { .tag = KMIP_TAG_KEY_VALUE_LOCATION_TYPE, + .enum_info = kmip_key_value_location_types, .is_mask = false }, + { .tag = KMIP_TAG_LINK_TYPE, + .enum_info = kmip_link_types, .is_mask = false }, + { .tag = KMIP_TAG_CLIENT_REGISTRATION_METHOD, + .enum_info = kmip_client_registration_methods, .is_mask = false }, + { .tag = KMIP_TAG_RNG_ALGORITHM, + .enum_info = kmip_rng_algorithms, .is_mask = false }, + { .tag = KMIP_TAG_DRBG_ALGORITHM, + .enum_info = kmip_drbg_algorithms, .is_mask = false }, + { .tag = KMIP_TAG_FIPS186_VARIANT, + .enum_info = kmip_fips186_variations, .is_mask = false }, + { .tag = KMIP_TAG_VALIDATION_AUTHORITY_TYPE, + .enum_info = kmip_validation_authority_types, .is_mask = false }, + { .tag = KMIP_TAG_VALIDATION_TYPE, + .enum_info = kmip_validation_types, .is_mask = false }, + { .tag = KMIP_TAG_UNWRAP_MODE, + .enum_info = kmip_unwrap_modes, .is_mask = false }, + { .tag = KMIP_TAG_DESTROY_ACTION, + .enum_info = kmip_destroy_actions, .is_mask = false }, + { .tag = KMIP_TAG_SHREDDING_ALGORITHM, + .enum_info = kmip_shredding_algorithms, .is_mask = false }, + { .tag = KMIP_TAG_RNG_MODE, + .enum_info = kmip_rng_modes, .is_mask = false }, + { .tag = KMIP_TAG_PROFILE_NAME, + .enum_info = kmip_profile_names, .is_mask = false }, + { .tag = 0, .enum_info = NULL, .is_mask = false }, +}; + +static const struct kmip_enum kmip_v1_attribute_names[] = { + { .val = KMIP_TAG_UNIQUE_IDENTIFIER, .name = "Unique Identifier" }, + { .val = KMIP_TAG_NAME, .name = "Name" }, + { .val = KMIP_TAG_OBJECT_TYPE, .name = "Object Type" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_ALGORITHM, + .name = "Cryptographic Algorithm" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_DOMAIN_PARAMETERS, + .name = "Cryptographic Domain Parameters" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_LENGTH, + .name = "Cryptographic Length" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_PARAMETERS, + .name = "Cryptographic Parameters" }, + { .val = KMIP_TAG_CERTIFICATE_TYPE, .name = "Certificate Type" }, + { .val = KMIP_TAG_CERTIFICATE_IDENTIFIER, + .name = "Certificate Identifier" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER, .name = "Certificate Issuer" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT, .name = "Certificate Subject" }, + { .val = KMIP_TAG_DIGEST, .name = "Digest" }, + { .val = KMIP_TAG_OPERATION_POLICY_NAME, + .name = "Operation Policy Name" }, + { .val = KMIP_TAG_CRYPTOGRAPHIC_USAGE_MASK, + .name = "Cryptographic Usage Mask" }, + { .val = KMIP_TAG_LEASE_TIME, .name = "Lease Time" }, + { .val = KMIP_TAG_USAGE_LIMITS, .name = "Usage Limits" }, + { .val = KMIP_TAG_STATE, .name = "State" }, + { .val = KMIP_TAG_INITIAL_DATE, .name = "Initial Date" }, + { .val = KMIP_TAG_ACTIVATION_DATE, .name = "Activation Date" }, + { .val = KMIP_TAG_PROCESS_START_DATE, .name = "Process Start Date" }, + { .val = KMIP_TAG_PROTECT_STOP_DATE, .name = "Protect Stop Date" }, + { .val = KMIP_TAG_DEACTIVATION_DATE, .name = "Deactivation Date" }, + { .val = KMIP_TAG_DESTROY_DATE, .name = "Destroy Date" }, + { .val = KMIP_TAG_COMPROMISE_OCCURRENCE_DATE, + .name = "Compromise Occurrence Date" }, + { .val = KMIP_TAG_COMPROMIZE_DATE, .name = "Compromise Date" }, + { .val = KMIP_TAG_REVOCATION_REASON, .name = "Revocation Reason" }, + { .val = KMIP_TAG_ARCHIVE_DATE, .name = "Archive Date" }, + { .val = KMIP_TAG_OBJECT_GROUP, .name = "Object Group" }, + { .val = KMIP_TAG_LINK, .name = "Link" }, + { .val = KMIP_TAG_APPLICATION_SPECIFIC_INFORMATION, + .name = "Application Specific Information" }, + { .val = KMIP_TAG_CONTACT_INFORMATION, .name = "Contact Information" }, + { .val = KMIP_TAG_LAST_CHANGE_DATE, .name = "Last Change Date" }, + { .val = KMIP_TAG_CUSTOM_ATTRIBUTE, .name = "Custom Attribute" }, + { .val = KMIP_TAG_ALTERNATE_NAME, .name = "Alternative Name" }, + { .val = KMIP_TAG_KEY_VALUE_PRESENT, .name = "Key Value Present" }, + { .val = KMIP_TAG_KEY_VALUE_LOCATION, .name = "Key Value Location" }, + { .val = KMIP_TAG_ORIGINAL_CREATION_DATE, + .name = "Original Creation Date" }, + { .val = KMIP_TAG_RANDOM_NUMBER_GENERATOR, + .name = "Random Number Generator" }, + { .val = KMIP_TAG_PKCS_12_FRIENDLY_NAME, + .name = "PKCS#12 Friendly Name" }, + { .val = KMIP_TAG_DESCRIPTION, .name = "Description" }, + { .val = KMIP_TAG_COMMENT, .name = "Comment" }, + { .val = KMIP_TAG_SENSITIVE, .name = "Sensitive" }, + { .val = KMIP_TAG_ALWAYS_SENSITIVE, .name = "Always Sensitive" }, + { .val = KMIP_TAG_EXTRACTABLE, .name = "Extractable" }, + { .val = KMIP_TAG_NEVER_EXTRACTABLE, .name = "Never Extractable" }, + /* + * KMIP v2.x attribute names (just for reference, will most likely + * not appear in a v1.x attribute list + */ + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_CN, + .name = "Certificate Subject CN" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_O, + .name = "Certificate Subject O" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_OU, + .name = "Certificate Subject OU" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_EMAIL, + .name = "Certificate Subject Email" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_C, + .name = "Certificate Subject C" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_ST, + .name = "Certificate Subject ST" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_L, + .name = "Certificate Subject L" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_UID, + .name = "Certificate Subject UID" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_SERIAL_NUMBER, + .name = "Certificate Subject Serial Number" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_TITLE, + .name = "Certificate Subject Title" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_DC, + .name = "Certificate Subject DC" }, + { .val = KMIP_TAG_CERTIFICATE_SUBJECT_DN_QUALIFIER, + .name = "Certificate Subject DN Qualifier" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_CN, + .name = "Certificate Issuer CN" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_O, + .name = "Certificate Issuer O" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_OU, + .name = "Certificate Issuer OU" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_EMAIL, + .name = "Certificate Issuer Email" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_C, + .name = "Certificate Issuer C" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_ST, + .name = "Certificate Issuer ST" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_L, + .name = "Certificate Issuer L" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_UID, + .name = "Certificate Issuer UID" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_SERIAL_NUMBER, + .name = "Certificate Issuer Serial Number" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_TITLE, + .name = "Certificate Issuer Title" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_DC, + .name = "Certificate Issuer DC" }, + { .val = KMIP_TAG_CERTIFICATE_ISSUER_DN_QUALIFIER, + .name = "Certificate Issuer DN Qualifier" }, + { .val = KMIP_TAG_CERTIFICATE_TYPE, .name = "Certificate Type" }, + { .val = KMIP_TAG_CERTIFICATE_LENGTH, .name = "Certificate Length" }, + { .val = KMIP_TAG_DIGITAL_SIGNATURE_ALGORITHM, + .name = "Digital Signature Algorithm" }, + { .val = KMIP_TAG_FRESH, .name = "Fresh" }, + { .val = KMIP_TAG_KEY_FORMAT_TYPE, .name = "Key Format Type" }, + { .val = KMIP_TAG_NIST_KEY_TYPE, .name = "NIST Key Type" }, + { .val = KMIP_TAG_OPAQUE_DATA_TYPE, .name = "Opaque Data Type" }, + { .val = KMIP_TAG_PROTECTION_LEVEL, .name = "Protection Level" }, + { .val = KMIP_TAG_PROTECTION_PERIOD, .name = "Protection Period" }, + { .val = KMIP_TAG_PROTECTION_STORAGE_MASK, + .name = "Protection Storage Mask" }, + { .val = KMIP_TAG_QUANTUM_SAFE, .name = "Quantum Safe" }, + { .val = KMIP_TAG_SHORT_UNIQUE_IDENTIFIER, + .name = "Short Unique Identifier" }, + { .val = KMIP_TAG_ATTRIBUTE, .name = "Vendor Attribute" }, + { .val = KMIP_TAG_X_509_CERTIFICATE_IDENTIFIER, + .name = "X.509 Certificate Identifier" }, + { .val = KMIP_TAG_X_509_CERTIFICATE_ISSUER, + .name = "X.509 Certificate Issuer" }, + { .val = KMIP_TAG_X_509_CERTIFICATE_SUBJECT, + .name = "X.509 Certificate Subject" }, + { .val = 0, .name = NULL }, +}; + +/** + * Return the name of the enumeration value, or NULL if the value is unknown + */ +static const char *kmip_enum_name_by_value(const struct kmip_enum *info, + uint32_t val) +{ + unsigned int i; + + for (i = 0; info[i].name != NULL; i++) { + if (info[i].val == val) + return info[i].name; + } + + return NULL; +} + +/** + * Return the enumeration value specified as enumeration name, or in hex + * notation. + */ +int kmip_enum_value_by_name_or_hex(const struct kmip_enum *info, + const char *name, uint32_t *value) +{ + unsigned int i; + int64_t val; + int rc; + + if (name == NULL || value == NULL) + return -EINVAL; + + for (i = 0; info[i].name != NULL; i++) { + if (strcmp(info[i].name, name) == 0) { + *value = info[i].val; + return 0; + } + } + + rc = kmip_parse_hex_int(name, &val); + if (rc != 0) + return rc; + + *value = val; + return 0; +} + +/* + * Get the name of an enumeration value belonging to the specified tag + */ +const char *kmip_enum_name_by_tag_value(enum kmip_tag tag, uint32_t val) +{ + int i; + + for (i = 0; enum_info[i].enum_info != NULL; i++) { + if (enum_info[i].tag != tag) + continue; + + return kmip_enum_name_by_value(enum_info[i].enum_info, val); + } + + return NULL; +} + +/** + * Return the enumeration value belonging to the specified tag, specified as + * enumeration name, or in hex notation. + */ +int kmip_enum_value_by_tag_name_or_hex(enum kmip_tag tag, const char *name, + uint32_t *value) +{ + int64_t val; + int i, rc; + + if (name == NULL || value == NULL) + return -EINVAL; + + for (i = 0; enum_info[i].enum_info != NULL; i++) { + if (enum_info[i].tag != tag) + continue; + + return kmip_enum_value_by_name_or_hex(enum_info[i].enum_info, + name, value); + } + + rc = kmip_parse_hex_int(name, &val); + if (rc != 0) + return rc; + + *value = val; + return 0; +} + +/** + * Return the name of the tag, or NULL if the tag is unknown + */ +const char *kmip_tag_name_by_tag(enum kmip_tag tag) +{ + return kmip_enum_name_by_value(kmip_tags, tag); +} + +/** + * Return the name or the hex representation of the tag + */ +const char *kmip_tag_name_or_hex_by_tag(enum kmip_tag tag, char tmp_buff[20]) +{ + const char *str; + + str = kmip_enum_name_by_value(kmip_tags, tag); + if (str == NULL) { + sprintf(tmp_buff, "0x%06x", tag); + str = tmp_buff; + } + return str; +} + +/** + * Return the tag value specified as tag name, or in hex notation. Returns 0 + * in case of an error. + */ +enum kmip_tag kmip_tag_by_name_or_hex(const char *name) +{ + uint32_t val; + int rc; + + rc = kmip_enum_value_by_name_or_hex(kmip_tags, name, &val); + if (rc != 0) + return 0; + + return val; +} + +/** + * Return the name of the type, or NULL if the type is unknown + */ +const char *kmip_type_name_by_type(enum kmip_type type) +{ + return kmip_enum_name_by_value(kmip_types, type); +} + +/** + * Return the type value specified as type name, or in hex notation. Returns 0 + * in case of an error. + */ +enum kmip_type kmip_type_by_name_or_hex(const char *name) +{ + uint32_t val; + int rc; + + rc = kmip_enum_value_by_name_or_hex(kmip_types, name, &val); + if (rc != 0) + return 0; + + return val; +} + +/** + * Return the KMIP v1.x attribute name of the tag, or NULL if the tag is unknown + */ +const char *kmip_v1_attr_name_by_tag(enum kmip_tag attr_tag) +{ + return kmip_enum_name_by_value(kmip_v1_attribute_names, attr_tag); +} + +/** + * Return the attribute tag value specified as KMIP v1.x attribute name. + * Returns 0 in case of an error. + */ +enum kmip_tag kmip_attr_tag_by_v1_attr_name(const char *name) +{ + uint32_t val; + int rc; + + rc = kmip_enum_value_by_name_or_hex(kmip_v1_attribute_names, name, + &val); + if (rc != 0) + return 0; + + return val; +} + +/** + * Returns true if the tag is a mask + */ +bool kmip_is_tag_mask(enum kmip_tag tag) +{ + int i; + + for (i = 0; enum_info[i].enum_info != NULL; i++) { + if (enum_info[i].tag != tag) + continue; + + return enum_info[i].is_mask; + } + + return false; +} + +/** + * Returns the enumeration info for the specified tag, or NULL, if the tag + * is not associated with an enumeration. + */ +const struct kmip_enum *kmip_enum_info_by_tag(enum kmip_tag tag) +{ + int i; + + for (i = 0; enum_info[i].enum_info != NULL; i++) { + if (enum_info[i].tag != tag) + continue; + + return enum_info[i].enum_info; + } + + return NULL; +} diff --git a/libkmipclient/names.h b/libkmipclient/names.h new file mode 100644 index 00000000..ee25ea6d --- /dev/null +++ b/libkmipclient/names.h @@ -0,0 +1,41 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ +#ifndef NAMES_H +#define NAMES_H + +#include + +#include "kmip.h" + +struct kmip_enum { + uint32_t val; + const char *name; +}; + + +const struct kmip_enum *kmip_enum_info_by_tag(enum kmip_tag tag); +bool kmip_is_tag_mask(enum kmip_tag tag); +int kmip_enum_value_by_name_or_hex(const struct kmip_enum *info, + const char *name, uint32_t *value); + +const char *kmip_enum_name_by_tag_value(enum kmip_tag tag, uint32_t val); +int kmip_enum_value_by_tag_name_or_hex(enum kmip_tag tag, const char *name, + uint32_t *value); + +const char *kmip_tag_name_by_tag(enum kmip_tag tag); +const char *kmip_tag_name_or_hex_by_tag(enum kmip_tag tag, char tmp_buff[20]); +enum kmip_tag kmip_tag_by_name_or_hex(const char *name); + +const char *kmip_type_name_by_type(enum kmip_type type); +enum kmip_type kmip_type_by_name_or_hex(const char *name); + +const char *kmip_v1_attr_name_by_tag(enum kmip_tag attr_tag); +enum kmip_tag kmip_attr_tag_by_v1_attr_name(const char *name); + +#endif diff --git a/libkmipclient/request.c b/libkmipclient/request.c new file mode 100644 index 00000000..a625aa49 --- /dev/null +++ b/libkmipclient/request.c @@ -0,0 +1,1795 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include +#include + +#include "kmip.h" +#include "names.h" + +/** + * Constructs a Protocol Version node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protocol Version Structure v1.0 + * Protocol Version Major Yes Integer v1.0 + * Protocol Version Minor Yes Integer v1.0 + * + * @param version the protocol version + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_protocol_version(const struct kmip_version *version) +{ + struct kmip_node *ret = NULL, *maj, *min; + + if (version == NULL) + return NULL; + + maj = kmip_node_new_integer(KMIP_TAG_PROTOCOL_VERSION_MAJOR, NULL, + version->major); + min = kmip_node_new_integer(KMIP_TAG_PROTOCOL_VERSION_MINOR, NULL, + version->minor); + if (maj == NULL || min == NULL) + goto out; + + ret = kmip_node_new_structure_va(KMIP_TAG_PROTOCOL_VERSION, NULL, 2, + maj, min); + +out: + kmip_node_free(maj); + kmip_node_free(min); + + return ret; +} + +/** + * Constructs a Profile Version node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Profile Version Structure v1.0 + * Profile Version Major Yes Integer v1.0 + * Profile Version Minor Yes Integer v1.0 + * + * @param version the profile version + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_profile_version(const struct kmip_version *version) +{ + struct kmip_node *ret = NULL, *maj, *min; + + if (version == NULL) + return NULL; + + maj = kmip_node_new_integer(KMIP_TAG_PROFILE_VERSION_MAJOR, NULL, + version->major); + min = kmip_node_new_integer(KMIP_TAG_PROFILE_VERSION_MINOR, NULL, + version->minor); + if (maj == NULL || min == NULL) + goto out; + + ret = kmip_node_new_structure_va(KMIP_TAG_PROFILE_VERSION, NULL, 2, + maj, min); + +out: + kmip_node_free(maj); + kmip_node_free(min); + + return ret; +} + +/** + * Constructs a Request Header node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Request Header Yes Structure v1.0 + * Protocol Version Yes Structure v1.0 + * Maximum Response Size No Integer v1.0 + * Client Correlation Value No Text String v1.4 + * Server Correlation Value No Text String v1.4 + * Asynchronous Indicator No Boolean v1.0 + * Attestation Capable Indic. No Boolean v1.2 + * Attestation Type No Enumeration v1.2 + * ... may be repeated + * Authentication No Structure v1.0 + * Batch Error Cont. Option No Enumeration v1.0 + * Batch Order Option No Boolean v1.0 + * Time Stamp No Date Time v1.0 + * Batch Count Yes Integer v1.0 + * + * @param version the protocol version. If NULL, the default + * protocol version is used + * @param max_response_size the maximum response size. Ignored if <= 0. + * @param client_corr_value the client correlation value. Ignored if NULL. + * @param server_corr_value the server correlation value. Ignored if NULL. + * @param asynchronous if true the request is asynchronous + * @param authentication the authentication node (can be NULL) + * @param batch_err_opt the batch error continuation option. Ignored if 0, + * or if batch_count is less than 2. + * @param batch_order_option the batch order option (true = execute in order) + * @param batch_count the batch count + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_request_header(const struct kmip_version *version, + int32_t max_response_size, + const char *client_corr_value, + const char *server_corr_value, + bool asynchronous, + struct kmip_node *authentication, + enum kmip_batch_error_cont_option batch_err_opt, + bool batch_order_option, + int32_t batch_count) +{ + struct kmip_node *ret = NULL, *err = NULL, *async = NULL, *tim = NULL; + struct kmip_node *max = NULL, *cnt = NULL, *ord = NULL, *ver = NULL; + struct kmip_node *ccorr = NULL, *scorr = NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + ver = kmip_new_protocol_version(version); + if (ver == NULL) + goto out; + + if (max_response_size > 0) { + max = kmip_node_new_integer(KMIP_TAG_MAXIMUM_RESPONSE_SIZE, + NULL, max_response_size); + if (max == NULL) + goto out; + } + + if (version->major == 1 && version->minor <= 3) { + client_corr_value = NULL; + server_corr_value = NULL; + } + + if (client_corr_value) { + ccorr = kmip_node_new_text_string( + KMIP_TAG_CLIENT_CORRELATION_VALUE, + NULL, client_corr_value); + if (ccorr == NULL) + goto out; + } + + if (server_corr_value) { + scorr = kmip_node_new_text_string( + KMIP_TAG_SERVER_CORRELATION_VALUE, + NULL, server_corr_value); + if (scorr == NULL) + goto out; + } + + if (asynchronous) { + async = kmip_node_new_boolean(KMIP_TAG_ASYNCHRONOUS_INDICATOR, + NULL, asynchronous); + if (async == NULL) + goto out; + } + + if (batch_err_opt != 0 && batch_count > 1) { + err = kmip_node_new_enumeration( + KMIP_TAG_BATCH_ERROR_CONTINUATION_OPTION, NULL, + batch_err_opt); + if (err == NULL) + goto out; + } + + ord = kmip_node_new_boolean(KMIP_TAG_BATCH_ORDER_OPTION, NULL, + batch_order_option); + if (ord == NULL) + goto out; + + tim = kmip_node_new_date_time(KMIP_TAG_TIME_STAMP, NULL, time(NULL)); + if (tim == NULL) + goto out; + + cnt = kmip_node_new_integer(KMIP_TAG_BATCH_COUNT, NULL, batch_count); + if (cnt == NULL) + goto out; + + ret = kmip_node_new_structure_va(KMIP_TAG_REQUEST_HEADER, NULL, 10, + ver, max, ccorr, scorr, authentication, + async, err, ord, tim, cnt); +out: + kmip_node_free(ver); + kmip_node_free(max); + kmip_node_free(async); + kmip_node_free(err); + kmip_node_free(ord); + kmip_node_free(tim); + kmip_node_free(cnt); + + return ret; +} + +/** + * Constructs a Request Batch Item node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Batch Item Yes Structure v1.0 + * Operation Yes Enumeration v1.0 + * Ephemeral No Boolean v2.0 + * Unique Batch Item ID No Byte String v1.0 + * Request Payload Yes Structure v1.0 + * Message Extension No Structure v1.0 + * + * @param operation the operation + * @param authentication A batch_id (can be NULL, req. if batch count > 0) + * @param batch_id_length the size of the batch ID + * @param payload the payload node + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_request_batch_item(enum kmip_operation operation, + unsigned char *batch_id, + uint32_t batch_id_length, + struct kmip_node *payload) +{ + struct kmip_node *ret = NULL, *op, *bid = NULL; + + if (payload == NULL) + return NULL; + + op = kmip_node_new_enumeration(KMIP_TAG_OPERATION, NULL, operation); + if (op == NULL) + return NULL; + + if (batch_id != NULL && batch_id_length > 0) { + bid = kmip_node_new_byte_string(KMIP_TAG_UNIQUE_BATCH_ITEM_ID, + NULL, batch_id, batch_id_length); + if (bid == NULL) + goto out; + } + + ret = kmip_node_new_structure_va(KMIP_TAG_BATCH_ITEM, NULL, 3, op, bid, + payload); + +out: + kmip_node_free(op); + kmip_node_free(bid); + + return ret; +} + +/** + * Constructs a Request Message node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Request Message Yes Structure v1.0 + * Request Header Yes Structure v1.0 + * Batch Item Yes Structure v1.0 + * ... may be repeated + * + * @param request_header the request header node + * @param batch_count the number of batch items to add + * @parambatch_items array of batch items + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_request(struct kmip_node *request_header, + int32_t batch_count, + struct kmip_node **batch_items) +{ + struct kmip_node *ret; + int rc = 0; + + if (request_header == NULL) + return NULL; + + ret = kmip_node_new_structure_va(KMIP_TAG_REQUEST_MESSAGE, NULL, 1, + request_header); + if (ret == NULL) + return NULL; + + rc = kmip_node_add_structure_elements(ret, batch_count, batch_items); + if (rc != 0) + goto error; + + return ret; + +error: + kmip_node_free(ret); + return NULL; +} + +/** + * Constructs a Request Message node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Request Message Yes Structure v1.0 + * Request Header Yes Structure v1.0 + * Batch Item Yes Structure v1.0 + * ... may be repeated + * + * @param request_header the request header node + * @param batch_count the number of batch items following + * @param batch items (struct kmip_node *) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_request_va(struct kmip_node *request_header, + int32_t batch_count, ...) +{ + struct kmip_node *ret, **bis = NULL; + va_list ap; + int32_t i; + + if (request_header == NULL) + return NULL; + + if (batch_count > 0) { + bis = calloc(batch_count, sizeof(struct kmip_node *)); + if (bis == NULL) + return NULL; + } + + va_start(ap, batch_count); + for (i = 0; i < batch_count; i++) + bis[i] = va_arg(ap, struct kmip_node *); + va_end(ap); + + ret = kmip_new_request(request_header, batch_count, bis); + + if (bis != NULL) + free(bis); + + return ret; +} + +/** + * Constructs a Query request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Query Function Yes Enumeration v1.0 + * ... may be repeated + * + * @param query_count the number of query function items following + * @param functions query function items + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_query_request_payload(unsigned int query_count, + const enum kmip_query_function *functions) +{ + struct kmip_node *rpl, *qf = NULL; + unsigned int i; + int rc = 0; + + if (query_count > 0 && functions == NULL) + return NULL; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 0); + if (rpl == NULL) + return NULL; + + for (i = 0; i < query_count; i++) { + qf = kmip_node_new_enumeration(KMIP_TAG_QUERY_FUNCTION, NULL, + functions[i]); + if (qf == NULL) + goto error; + + rc = kmip_node_add_structure_element(rpl, qf); + if (rc != 0) + break; + kmip_node_free(qf); + qf = NULL; + } + + if (rc != 0) + goto error; + + return rpl; + +error: + kmip_node_free(rpl); + kmip_node_free(qf); + return NULL; +} + +/** + * Constructs a Query request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Query Function Yes Enumeration v1.0 + * ... may be repeated + * + * @param query_count the number of query function items following + * @param query items (enum kmip_query_function) + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_query_request_payload_va(unsigned int query_count, + ...) +{ + enum kmip_query_function *qfs = NULL; + struct kmip_node *rpl; + unsigned int i; + va_list ap; + + if (query_count > 0) { + qfs = calloc(query_count, sizeof(enum kmip_query_function)); + if (qfs == NULL) + return NULL; + } + + va_start(ap, query_count); + for (i = 0; i < query_count; i++) + qfs[i] = va_arg(ap, enum kmip_query_function); + va_end(ap); + + rpl = kmip_new_query_request_payload(query_count, qfs); + + if (qfs != NULL) + free(qfs); + + return rpl; +} + +static const struct kmip_version kmip_versions[] = { + { .major = 1, .minor = 0 }, + { .major = 1, .minor = 1 }, + { .major = 1, .minor = 2 }, + { .major = 1, .minor = 3 }, + { .major = 1, .minor = 4 }, + { .major = 2, .minor = 0 }, + { .major = 2, .minor = 1 }, +}; + +/** + * Constructs a Discover Versions request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Protocol Version No Structure v1.2 + * ... may be repeated + * + * @param version_count the number of version items following. If -1 then + * all currently supported versions are added. + * @param versions array of version items + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_discover_versions_payload(int version_count, + const struct kmip_version *versions) +{ + struct kmip_node *rpl, *ver = NULL; + int rc = 0; + int i; + + if (version_count > 0 && versions == NULL) + return NULL; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 0); + if (rpl == NULL) + return NULL; + + + if (version_count < 0) { + versions = kmip_versions; + version_count = sizeof(kmip_versions) / + sizeof(struct kmip_version); + } + + for (i = 0; i < version_count; i++) { + ver = kmip_new_protocol_version(&versions[i]); + if (ver == NULL) + goto error; + + rc = kmip_node_add_structure_element(rpl, ver); + if (rc != 0) + break; + kmip_node_free(ver); + ver = NULL; + } + + + if (rc != 0) + goto error; + + return rpl; + +error: + kmip_node_free(rpl); + kmip_node_free(ver); + return NULL; +} + +/** + * Constructs a Discover Versions request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Protocol Version No Structure v1.2 + * ... may be repeated + * + * @param version_count the number of version items following. If -1 then + * all currently supported versions are added. + * @param version items (struct kmip_version) + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_discover_versions_payload_va(int version_count, ...) +{ + struct kmip_version *versions = NULL; + struct kmip_node *rpl; + va_list ap; + int i; + + if (version_count > 0) { + versions = calloc(version_count, sizeof(struct kmip_version)); + if (versions == NULL) + return NULL; + } + + va_start(ap, version_count); + for (i = 0; i < version_count; i++) + versions[i] = *va_arg(ap, struct kmip_version *); + va_end(ap); + + rpl = kmip_new_discover_versions_payload(version_count, versions); + + if (versions != NULL) + free(versions); + + return rpl; +} + +/** + * Constructs a Protection Storage Masks node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Storage Masks Yes Structure v2.0 + * Protection Storage Mask Yes Integer v2.0 + * ... may be repeated + * + * @param masks_count the number of protection storage masks + * @param masks array of mask items + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_protection_storage_masks(unsigned int masks_count, + int32_t *masks) +{ + struct kmip_node *ret, *psm; + unsigned int i; + int rc = 0; + + if (masks_count > 0 && masks == NULL) + return NULL; + + ret = kmip_node_new_structure_va(KMIP_TAG_PROTECTION_STORAGE_MASKS, + NULL, 0); + if (ret == NULL) + return NULL; + + for (i = 0; i < masks_count; i++) { + psm = kmip_node_new_integer(KMIP_TAG_PROTECTION_STORAGE_MASK, + NULL, masks[i]); + if (psm == NULL) + break; + + rc = kmip_node_add_structure_element(ret, psm); + if (rc != 0) + break; + kmip_node_free(psm); + psm = NULL; + } + + if (rc != 0) + goto error; + + return ret; + +error: + kmip_node_free(ret); + kmip_node_free(psm); + return NULL; +} + +/** + * Constructs a Protection Storage Masks node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protection Storage Masks Yes Structure v2.0 + * Protection Storage Mask Yes Integer v2.0 + * ... may be repeated + * + * @param masks_count the number of protection storage masks following + * @param mask items (int32_t) + * + * @returns the allocated node, or NULL in case of an error. + */ +struct kmip_node *kmip_new_protection_storage_masks_va(unsigned int masks_count, + ...) +{ + int32_t *masks = NULL; + struct kmip_node *ret; + unsigned int i; + va_list ap; + + if (masks_count > 0) { + masks = calloc(masks_count, sizeof(int32_t)); + if (masks == NULL) + return NULL; + } + + va_start(ap, masks_count); + for (i = 0; i < masks_count; i++) + masks[i] = va_arg(ap, int32_t); + va_end(ap); + + ret = kmip_new_protection_storage_masks(masks_count, masks); + + if (masks != NULL) + free(masks); + + return ret; +} + +/** + * Constructs a Create request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Object Type Yes Enumeration v1.0 + * Template-Attribute Yes(v1.x) Structure v1.x only + * Attributes Yes(v2.x) Structure v2.x only + * Protection Storage Masks No Structure v2.x + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param obj_type the object type to create + * @paran prot_storage_masks the protection storage masks (can be NULL) + * @param attrs_count the number of attributes following (can be 0) + * @param attrs the array of attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_create_request_payload( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, + struct kmip_node **attrs) +{ + struct kmip_node *rpl = NULL, *otyp = NULL, *att; + + if (attrs_count > 0 && attrs == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + otyp = kmip_new_object_type(obj_type); + if (otyp == NULL) + return NULL; + + if (version->major < 2) + prot_storage_masks = NULL; + + att = kmip_new_attributes(version, KMIP_TAG_ATTRIBUTES, attrs_count, + attrs); + if (att == NULL) + goto out; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 3, + otyp, att, prot_storage_masks); + +out: + kmip_node_free(otyp); + kmip_node_free(att); + + return rpl; +} + + +/** + * Constructs a Create request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Object Type Yes Enumeration v1.0 + * Template-Attribute Yes(v1.x) Structure v1.x only + * Attributes Yes(v2.x) Structure v2.x only + * Protection Storage Masks No Structure v2.x + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param obj_type the object type to create + * @paran prot_storage_masks the protection storage masks (can be NULL) + * @param attrs_count the number of attributes following (can be 0) + * @param the attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_create_request_payload_va( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, ...) +{ + struct kmip_node *ret, **attrs = NULL; + unsigned int i, k; + va_list ap; + + if (attrs_count > 0) { + attrs = calloc(attrs_count, sizeof(struct kmip_node *)); + if (attrs == NULL) + return NULL; + } + + va_start(ap, attrs_count); + for (i = 0, k = 0; i < attrs_count; i++) { + attrs[k] = va_arg(ap, struct kmip_node *); + if (attrs[k] != NULL) + k++; + } + va_end(ap); + + ret = kmip_new_create_request_payload(version, obj_type, + prot_storage_masks, k, + attrs); + if (attrs != NULL) + free(attrs); + + return ret; +} + +/** + * Constructs a Get Attribute List request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param unique_id the unique id of the object to address (can be NULL) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_get_attribute_list_request_payload( + struct kmip_node *unique_id) +{ + struct kmip_node *rpl; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 1, + unique_id); + + return rpl; +} + +/** + * Constructs a Get Attributes request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Name No Text String v1.x only + * ... may be repeated + * Attribute Reference No Enumeration v2.x only + * Structure v2.x only + * ... may be repeated + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param unique_id the unique id of the object to address + * @param num_attrs number of attribute references following + * @param attr_refs array of attribute references (struct kmip_node *) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_get_attributes_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + unsigned int num_attrs, + struct kmip_node **attr_refs) +{ + struct kmip_node *rpl, *v2_attr_ref, *v1_attr_name; + unsigned int i; + int rc = 0; + + if (num_attrs > 0 && attr_refs == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 1, + unique_id); + + for (i = 0; i < num_attrs; i++) { + v2_attr_ref = attr_refs[i]; + if (v2_attr_ref == NULL) + continue; + + if (version->major == 1) { + /* KMIP v1.x */ + v1_attr_name = kmip_new_attribute_name_v1(v2_attr_ref); + if (v1_attr_name == NULL) { + rc = -EBADMSG; + break; + } + + rc = kmip_node_add_structure_element(rpl, v1_attr_name); + kmip_node_free(v1_attr_name); + } else { + /* KMIP >= v2.0 */ + rc = kmip_node_add_structure_element(rpl, v2_attr_ref); + } + + if (rc != 0) + break; + } + + if (rc != 0) + goto error; + + return rpl; + +error: + kmip_node_free(rpl); + return NULL; +} + +/** + * Constructs a Get Attributes request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Name No Text String v1.x only + * ... may be repeated + * Attribute Reference No Enumeration v2.x only + * Structure v2.x only + * ... may be repeated + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param unique_id the unique id of the object to address + * @param num_attrs number of attribute references following + * @param attribute references (struct kmip_node *) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_get_attributes_request_payload_va( + const struct kmip_version *version, + struct kmip_node *unique_id, + unsigned int num_attrs, ...) +{ + struct kmip_node *ret, **attr_refs = NULL; + unsigned int i, k; + va_list ap; + + if (num_attrs > 0) { + attr_refs = calloc(num_attrs, sizeof(struct kmip_node *)); + if (attr_refs == NULL) + return NULL; + } + + va_start(ap, num_attrs); + for (i = 0, k = 0; i < num_attrs; i++) { + attr_refs[k] = va_arg(ap, struct kmip_node *); + if (attr_refs[k] != NULL) + k++; + } + va_end(ap); + + ret = kmip_new_get_attributes_request_payload(version, unique_id, + k, attr_refs); + if (attr_refs != NULL) + free(attr_refs); + + return ret; +} + +/** + * Constructs a Add Attribute request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Yes Structure v1.x only + * or + * New Attribute Yes Structure v2.x only + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param unique_id the unique id of the object to address + * @param v2_attr the attribute to add (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_add_attribute_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + struct kmip_node *v2_attr) +{ + struct kmip_node *rpl, *new_attr, *v1_attr; + int rc; + + if (v2_attr == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + if (version->major == 1) { + /* KMIP v1.x */ + rc = kmip_v1_attr_from_v2_attr(v2_attr, &v1_attr); + if (rc != 0) + return NULL; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 2, unique_id, v1_attr); + kmip_node_free(v1_attr); + } else { + /* KMIP >= v2.0 */ + new_attr = kmip_new_current_new_attribute(true, v2_attr); + if (new_attr == NULL) + return NULL; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 2, unique_id, new_attr); + kmip_node_free(new_attr); + } + + return rpl; +} + +/** + * Constructs a Modify Attribute request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Yes Structure v1.x only + * or + * Current Attribute No Structure v2.x only + * New Attribute Yes Structure v2.x only + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param unique_id the unique id of the object to address + * @param v2_current the current attribute (as KMIP v2.x attribute). + * Can be NULL, ignored for KMIP v1.x. + * @param v2_attr the attribute to modify (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_modify_attribute_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + struct kmip_node *v2_current, + struct kmip_node *v2_attr) +{ + struct kmip_node *rpl, *new_attr, *cur_attr = NULL, *v1_attr; + int rc; + + if (v2_attr == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + if (version->major == 1) { + /* KMIP v1.x */ + rc = kmip_v1_attr_from_v2_attr(v2_attr, &v1_attr); + if (rc != 0) + return NULL; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 2, unique_id, v1_attr); + kmip_node_free(v1_attr); + } else { + /* KMIP >= v2.0 */ + new_attr = kmip_new_current_new_attribute(true, v2_attr); + if (new_attr == NULL) + return NULL; + + if (v2_current != NULL) { + cur_attr = kmip_new_current_new_attribute(false, + v2_current); + if (cur_attr == NULL) { + kmip_node_free(new_attr); + return NULL; + } + } + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 3, unique_id, cur_attr, + new_attr); + kmip_node_free(new_attr); + if (cur_attr != NULL) + kmip_node_free(cur_attr); + } + + return rpl; +} + +/** + * Constructs a Set Attribute request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * New Attribute Yes Structure v2.x only + * + * KMIP v1.x does not have a Set Attribute operation. + * + * @param unique_id the unique id of the object to address + * @param v2_attr the attribute to set (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_set_attribute_v2_request_payload( + struct kmip_node *unique_id, + struct kmip_node *v2_attr) +{ + struct kmip_node *rpl, *new_attr; + + if (v2_attr == NULL) + return NULL; + + new_attr = kmip_new_current_new_attribute(true, v2_attr); + if (new_attr == NULL) + return NULL; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 2, + unique_id, new_attr); + kmip_node_free(new_attr); + + return rpl; +} + +/** + * Constructs a Delete Attribute request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Name Yes Text String v1.x only + * Attribute Index No Integer v1.x only + * or + * Current Attribute No Structure v2.x only + * Attribute Reference No Structure v2.x only + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param unique_id the unique id of the object to address + * @param v2_current the current attribute (as KMIP v2.x attribute). + * Can be NULL. + * @param attr_ref the attribute to modify (as KMIP v2.x attribute + * reference). Either v2_current or attr_ref can be + * specified. + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_delete_attribute_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + struct kmip_node *v2_current, + struct kmip_node *attr_ref) +{ + struct kmip_node *rpl, *cur_attr = NULL, *nam = NULL; + const char *vendor_id, *attr_name, *name; + char *custom_name = NULL; + int rc; + + if (v2_current != NULL && attr_ref != NULL) + return NULL; + if (v2_current == NULL && attr_ref == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + if (version->major == 1) { + /* KMIP v1.x */ + if (v2_current != NULL) { + if (kmip_node_get_tag(v2_current) == + KMIP_TAG_ATTRIBUTE) { + /* Special handling for v2.x Vendor Attribute */ + rc = kmip_get_vendor_attribute(v2_current, + &vendor_id, + &attr_name, + NULL); + if (rc != 0) + return NULL; + + custom_name = kmip_build_v1_custom_attr_name( + vendor_id, attr_name); + if (custom_name == NULL) + return NULL; + + name = custom_name; + } else { + name = kmip_v1_attr_name_by_tag( + kmip_node_get_tag(v2_current)); + } + + nam = kmip_node_new_text_string(KMIP_TAG_ATTRIBUTE_NAME, + NULL, name); + if (custom_name != NULL) + free(custom_name); + } else if (attr_ref != NULL) { + nam = kmip_new_attribute_name_v1(attr_ref); + } + if (nam == NULL) + return NULL; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 2, unique_id, nam); + kmip_node_free(nam); + } else { + /* KMIP >= v2.0 */ + if (v2_current != NULL) { + cur_attr = kmip_new_current_new_attribute(false, + v2_current); + if (cur_attr == NULL) + return NULL; + } + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 3, unique_id, cur_attr, + attr_ref); + if (cur_attr != NULL) + kmip_node_free(cur_attr); + } + + return rpl; +} + +/** + * Constructs an Activate request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param unique_id the unique id of the object to address + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_activate_request_payload(struct kmip_node *unique_id) +{ + + return kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 1, + unique_id); +} + +/** + * Constructs an Destroy request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param unique_id the unique id of the object to address + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_destroy_request_payload(struct kmip_node *unique_id) +{ + + return kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 1, + unique_id); +} + +/** + * Constructs an Archive request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param unique_id the unique id of the object to address + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_archive_request_payload(struct kmip_node *unique_id) +{ + + return kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 1, + unique_id); +} + +/** + * Constructs an Recover request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param unique_id the unique id of the object to address + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_recover_request_payload(struct kmip_node *unique_id) +{ + + return kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 1, + unique_id); +} + +/** + * Constructs an Revoke request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Revocation Reason Yes Structure v1.0 + * Revocation Reason Code Yes Enumeration v1.0 + * Revocation Message No Text String v1.0 + * Compromise Occurrence Date No Date Time v1.0 + * + * @param unique_id the unique id of the object to address + * @param rsn the revocation reason + * @param message the revocation message (can be NULL) + * @param compromise_date the date when he compromise happened (can be 0) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_revoke_request_payload(struct kmip_node *unique_id, + enum kmip_revoke_reason rsn, + const char *message, + uint64_t compromise_date) +{ + struct kmip_node *rsn_code, *reason = NULL, *rsn_msg = NULL; + struct kmip_node *rpl = NULL, *date = NULL; + + rsn_code = kmip_node_new_enumeration(KMIP_TAG_REVOCATION_REASON_CODE, + NULL, rsn); + if (rsn_code == NULL) + return NULL; + + if (message != NULL) { + rsn_msg = kmip_node_new_text_string(KMIP_TAG_REVOCATION_MESSAGE, + NULL, message); + if (rsn_msg == NULL) + goto out; + + } + + reason = kmip_node_new_structure_va(KMIP_TAG_REVOCATION_REASON, NULL, 2, + rsn_code, rsn_msg); + if (reason == NULL) + goto out; + + switch (rsn) { + case KMIP_REVOK_RSN_KEY_COMPROMISE: + case KMIP_REVOK_RSN_CA_COMPROMISE: + if (compromise_date != 0) { + date = kmip_node_new_date_time( + KMIP_TAG_COMPROMISE_OCCURRENCE_DATE, + NULL, compromise_date); + if (date == NULL) + goto out; + } + break; + default: + /*Compromise date is ignored on other reasons */ + break; + } + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 3, + unique_id, reason, date); + +out: + kmip_node_free(rsn_code); + kmip_node_free(rsn_msg); + kmip_node_free(reason); + kmip_node_free(date); + + return rpl; +} + +/** + * Constructs an Locate request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Maximum Items No Integer v1.0 + * Offset Items No Integer v1.3 + * Storage Status Mask No Integer v1.0 + * Object Group Member No Enumeration v1.2 + * Attribute No Structure v1.x only + * ... may be repeated + * Attributes Yes Structure v2.x only + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param max_items the maximum numbers of items to return. If <= 0 + * then no limit is assumed. + * @param offset_items the number of items to skip If <= 0 then no offset + * is assumed. Ignored for KMIP <= v1.2. + * @param storage_status the storage status filter. If 0, then no filter is + * used and only on-line objects are returned. + * @param obj_group the object group filter. If 0 then no object group + * filter is used. Ignored for KMIP <= v1.1. + * @param attrs_count the number of attributes following (can be 0) + * @param attrs the array of attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_locate_request_payload( + const struct kmip_version *version, + int32_t max_items, int32_t offset_items, + enum kmip_storage_status_mask storage_status, + enum kmip_object_group_member obj_group, + unsigned int attrs_count, + struct kmip_node **attrs) +{ + struct kmip_node *max = NULL, *ofs = NULL, *stm = NULL, *grp = NULL; + struct kmip_node *rpl = NULL, *att, *v2_attr, *v1_attr; + unsigned int i; + int rc; + + if (attrs_count > 0 && attrs == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + if (max_items > 0) { + max = kmip_node_new_integer(KMIP_TAG_MAXIMUM_ITEMS, NULL, + max_items); + if (max == NULL) + return NULL; + } + + if (offset_items > 0 && (version->major > 1 || + (version->major == 1 && version->minor > 2))) { + ofs = kmip_node_new_integer(KMIP_TAG_OFFSET_ITEMS, NULL, + offset_items); + if (ofs == NULL) + goto out; + } + + if (storage_status != 0) { + stm = kmip_node_new_integer(KMIP_TAG_STORAGE_STATUS_MASK, NULL, + storage_status); + if (stm == NULL) + goto out; + } + + if (obj_group > 0 && (version->major > 1 || version->minor > 1)) { + grp = kmip_node_new_enumeration(KMIP_TAG_OBJECT_GROUP_MEMBER, + NULL, obj_group); + if (grp == NULL) + goto out; + } + + if (version->major == 1) { + /* KMIP v1.x */ + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 4, max, ofs, stm, grp); + if (rpl == NULL) + goto out; + + for (i = 0; i < attrs_count; i++) { + v2_attr = attrs[i]; + if (v2_attr == NULL) + continue; + + rc = kmip_v1_attr_from_v2_attr(v2_attr, &v1_attr); + if (rc != 0) + goto error; + + rc = kmip_node_add_structure_element(rpl, v1_attr); + kmip_node_free(v1_attr); + if (rc != 0) + goto error; + } + } else { + /* KMIP >= v2.0 */ + att = kmip_new_attributes(version, KMIP_TAG_ATTRIBUTES, + attrs_count, attrs); + if (att == NULL) + goto out; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, + 5, max, ofs, stm, grp, att); + kmip_node_free(att); + } + + goto out; + +error: + kmip_node_free(rpl); + rpl = NULL; + +out: + kmip_node_free(max); + kmip_node_free(ofs); + kmip_node_free(stm); + kmip_node_free(grp); + + return rpl; +} + +/** + * Constructs an Locate request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Maximum Items No Integer v1.0 + * Offset Items No Integer v1.3 + * Storage Status Mask No Integer v1.0 + * Object Group Member No Enumeration v1.2 + * Attribute No Structure v1.x only + * ... may be repeated + * Attributes Yes Structure v2.x only + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param max_items the maximum numbers of items to return. If <= 0 + * then no limit is assumed. + * @param offset_items the number of items to skip If <= 0 then no offset + * is assumed. Ignored for KMIP <= v1.2. + * @param storage_status the storage status filter. If 0, then no filter is + * used and only on-line objects are returned. + * @param obj_group the object group filter. If 0 then no object group + * filter is used. Ignored for KMIP <= v1.1. + * @param attrs_count the number of attributes following (can be 0) + * @param the attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_locate_request_payload_va( + const struct kmip_version *version, + int32_t max_items, int32_t offset_items, + enum kmip_storage_status_mask storage_status, + enum kmip_object_group_member obj_group, + unsigned int attrs_count, ...) +{ + struct kmip_node *ret, **attrs = NULL; + unsigned int i, k; + va_list ap; + + if (attrs_count > 0) { + attrs = calloc(attrs_count, sizeof(struct kmip_node *)); + if (attrs == NULL) + return NULL; + } + + va_start(ap, attrs_count); + for (i = 0, k = 0; i < attrs_count; i++) { + attrs[k] = va_arg(ap, struct kmip_node *); + if (attrs[k] != NULL) + k++; + } + va_end(ap); + + ret = kmip_new_locate_request_payload(version, max_items, offset_items, + storage_status, obj_group, + k, attrs); + if (attrs != NULL) + free(attrs); + + return ret; +} + +/** + * Constructs an Register request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Object Type Yes Enumeration v1.0 + * Template-Attribute Yes(v1.x) Structure v1.x only + * Attributes Yes(v2.x) Structure v2.x only + * Yes Structure v1.0 + * Protection Storage Masks No Structure v2.x + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param obj_type the object type to register + * @param object the object to register + * @paran prot_storage_masks the protection storage masks (can be NULL) + * @param attrs_count the number of attributes following (can be 0) + * @param attrs the array of attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_register_request_payload( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *object, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, + struct kmip_node **attrs) +{ + struct kmip_node *rpl = NULL, *otyp = NULL, *att; + + if (object == NULL) + return NULL; + if (attrs_count > 0 && attrs == NULL) + return NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + otyp = kmip_new_object_type(obj_type); + if (otyp == NULL) + return NULL; + + if (version->major < 2) + prot_storage_masks = NULL; + + att = kmip_new_attributes(version, KMIP_TAG_ATTRIBUTES, attrs_count, + attrs); + + if (att == NULL) + goto out; + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 4, + otyp, att, object, + prot_storage_masks); + +out: + kmip_node_free(otyp); + kmip_node_free(att); + + return rpl; +} + +/** + * Constructs an Register request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Object Type Yes Enumeration v1.0 + * Template-Attribute Yes(v1.x) Structure v1.x only + * Attributes Yes(v2.x) Structure v2.x only + * Yes Structure v1.0 + * Protection Storage Masks No Structure v2.x + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param obj_type the object type to register + * @param object the object to register + * @paran prot_storage_masks the protection storage masks (can be NULL) + * @param attrs_count the number of attributes following (can be 0) + * @param the attributes (as KMIP v2.x attribute) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_register_request_payload_va( + const struct kmip_version *version, + enum kmip_object_type obj_type, + struct kmip_node *object, + struct kmip_node *prot_storage_masks, + unsigned int attrs_count, ...) +{ + struct kmip_node *ret, **attrs = NULL; + unsigned int i, k; + va_list ap; + + if (attrs_count > 0) { + attrs = calloc(attrs_count, sizeof(struct kmip_node *)); + if (attrs == NULL) + return NULL; + } + + va_start(ap, attrs_count); + for (i = 0, k = 0; i < attrs_count; i++) { + attrs[k] = va_arg(ap, struct kmip_node *); + if (attrs[k] != NULL) + k++; + } + va_end(ap); + + ret = kmip_new_register_request_payload(version, obj_type, object, + prot_storage_masks, + k, attrs); + if (attrs != NULL) + free(attrs); + + return ret; +} + +/** + * Constructs an Get request payload: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier No Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Key Format Type No Enumeration v1.0 + * Key Wrap Type No Enumeration v1.4 + * Key Compression Type No Enumeration v1.0 + * Key Wrapping Specification No Structure v1.0 + * + * @param version the protocol version. If null, the current default + * protocol version is used. + * @param unique_id the unique id of the object to get + * @param format_type the format type of the key (ignored if 0) + * @paran wrap_type the wrap type (ignored if 0) + * @param compr_type the compression type (ignored if 0) + * @param wrap_specification the key wrapping specification node (can be NULL) + * + * @returns the allocated node, or NULL in case of an error. + * The reference counts of the nodes specified as parameters which are added to + * the newly allocated node are increased. The caller must free its reference + * via kmip_node_free() if no longer needed. + */ +struct kmip_node *kmip_new_get_request_payload( + const struct kmip_version *version, + struct kmip_node *unique_id, + enum kmip_key_format_type format_type, + enum kmip_key_wrap_type wrap_type, + enum kmip_key_compression_type compr_type, + struct kmip_node *wrap_specification) +{ + struct kmip_node *rpl = NULL, *fmt = NULL, *wt = NULL, *cmpt = NULL; + + if (version == NULL) + version = kmip_get_default_protocol_version(); + + if (format_type != 0) { + fmt = kmip_node_new_enumeration(KMIP_TAG_KEY_FORMAT_TYPE, NULL, + format_type); + if (fmt == NULL) + goto out; + } + + if (wrap_type != 0 && (version->major > 1 || + (version->major == 1 && version->minor > 3))) { + wt = kmip_node_new_enumeration(KMIP_TAG_KEY_WRAP_TYPE, NULL, + wrap_type); + if (wt == NULL) + goto out; + } + + if (compr_type != 0) { + cmpt = kmip_node_new_enumeration(KMIP_TAG_KEY_COMPRESSION_TYPE, + NULL, compr_type); + if (cmpt == NULL) + goto out; + } + + rpl = kmip_node_new_structure_va(KMIP_TAG_REQUEST_PAYLOAD, NULL, 5, + unique_id, fmt, wt, cmpt, + wrap_specification); + +out: + kmip_node_free(fmt); + kmip_node_free(wt); + kmip_node_free(cmpt); + + return rpl; +} + diff --git a/libkmipclient/response.c b/libkmipclient/response.c new file mode 100644 index 00000000..7dcb7c89 --- /dev/null +++ b/libkmipclient/response.c @@ -0,0 +1,1377 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include +#include + +#include "kmip.h" + +/** + * Gets the version information from a Protocol Version node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Protocol Version Structure v1.0 + * Protocol Version Major Yes Integer v1.0 + * Protocol Version Minor Yes Integer v1.0 + * + * @param node the KMIP node + * @param version On return: the protocol version + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_protocol_version(const struct kmip_node *node, + struct kmip_version *version) +{ + struct kmip_node *maj, *min; + int rc = 0; + + if (node == NULL || version == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_PROTOCOL_VERSION) + return -EBADMSG; + + maj = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_PROTOCOL_VERSION_MAJOR, 0); + min = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_PROTOCOL_VERSION_MINOR, 0); + if (maj == NULL || min == NULL) { + rc = -EBADMSG; + goto out; + } + + version->major = kmip_node_get_integer(maj); + version->minor = kmip_node_get_integer(min); + +out: + kmip_node_free(maj); + kmip_node_free(min); + + return rc; +} + +/** + * Gets the version information from a Profile Version node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Profile Version Structure v1.0 + * Profile Version Major Yes Integer v1.0 + * Profile Version Minor Yes Integer v1.0 + * + * @param node the KMIP node + * @param version On return: the profile version + * + * @returns 0 on success, or a negative errno in case of an error + */ +int kmip_get_profile_version(const struct kmip_node *node, + struct kmip_version *version) +{ + struct kmip_node *maj, *min; + int rc = 0; + + if (node == NULL || version == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_PROFILE_VERSION) + return -EBADMSG; + + maj = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_PROFILE_VERSION_MAJOR, 0); + min = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_PROFILE_VERSION_MINOR, 0); + if (maj == NULL || min == NULL) { + rc = -EBADMSG; + goto out; + } + + version->major = kmip_node_get_integer(maj); + version->minor = kmip_node_get_integer(min); + +out: + kmip_node_free(maj); + kmip_node_free(min); + + return rc; +} + +/** + * Gets information from a Response Header node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Response Header Yes Structure v1.0 + * Protocol Version Yes Structure v1.0 + * Time Stamp No Date Time v1.0 + * Nonce No Structure v1.2 + * Server Hashed Password No Byte String v2.0 + * Attestation Type No Enumeration v1.2 + * ... may be repeated + * Client Correlation Value No Text String v1.4 + * Server Correlation Value No Text String v1.4 + * Batch Count Yes Integer v1.0 + * + * @param node the KMIP node + * @param version the protocol version (can be NULL) + * @param time_stamp the time stamp (can be NULL) + * @param client_corr_value the client correlation value. Can be NULL. + * @param server_corr_value the server correlation value. Can be NULL. + * @param batch_count the batch count (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned node is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_response_header(const struct kmip_node *node, + struct kmip_version *version, + int64_t *time_stamp, + const char **client_corr_value, + const char **server_corr_value, + int32_t *batch_count) +{ + struct kmip_node *n; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_HEADER) + return -EBADMSG; + + if (time_stamp != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_TIME_STAMP, 0); + if (n == NULL) + return -EBADMSG; + *time_stamp = kmip_node_get_date_time(n); + kmip_node_free(n); + } + + if (batch_count != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_BATCH_COUNT, 0); + if (n == NULL) + return -EBADMSG; + *batch_count = kmip_node_get_integer(n); + kmip_node_free(n); + } + + if (version != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_PROTOCOL_VERSION, 0); + if (n == NULL) + return -EBADMSG; + rc = kmip_get_protocol_version(n, version); + kmip_node_free(n); + if (rc != 0) + return rc; + } + + if (client_corr_value != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_CLIENT_CORRELATION_VALUE, 0); + if (n == NULL) + return -EBADMSG; + *client_corr_value = kmip_node_get_text_string(n); + kmip_node_free(n); + } + + if (server_corr_value != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_SERVER_CORRELATION_VALUE, 0); + if (n == NULL) + return -EBADMSG; + *server_corr_value = kmip_node_get_text_string(n); + kmip_node_free(n); + } + + return 0; +} + +/** + * Gets information from a Response Batch Item node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Batch Item Yes Structure v1.0 + * Operation Yes Enumeration v1.0 + * Unique Batch Item ID No Byte String v1.0 + * Result Status Yes Enumeration v1.0 + * Result Reason No/Yes Enumeration v1.0 + * Result Message No/Yes Text String v1.0 + * Asynchronous Correl. Value No/Yes Byte String v1.0 + * Response Payload Yes Structure v1.0 + * Message Extension No Structure v1.0 + * + * @param node the KMIP node + * @param operation the operation (can be NULL) + * @param batch_id the batch ID (can be NULL) + * @param batch_id_length the batch ID length (can be NULL) + * @param status the result status (can be NULL) + * @param reason the result reason (can be NULL) + * @param message the result message (can be NULL) + * @param async_corr_value the asynchronous correlation value (can be NULL) + * @param async_corr_value_len the length if the async corr. value (can be NULL) + * @param payload the response payload (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned node is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_response_batch_item(const struct kmip_node *node, + enum kmip_operation *operation, + const unsigned char **batch_id, + uint32_t *batch_id_length, + enum kmip_result_status *status, + enum kmip_result_reason *reason, + const char **message, + const unsigned char **async_corr_value, + uint32_t *async_corr_value_len, + struct kmip_node **payload) +{ + struct kmip_node *n; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_BATCH_ITEM) + return -EBADMSG; + + if (operation != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_OPERATION, 0); + if (n == NULL) + return -EBADMSG; + *operation = kmip_node_get_enumeration(n); + kmip_node_free(n); + } + + if (batch_id != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_BATCH_ITEM_ID, 0); + if (n == NULL) { + *batch_id = NULL; + if (batch_id_length != NULL) + *batch_id_length = 0; + } else { + *batch_id = kmip_node_get_byte_string(n, + batch_id_length); + kmip_node_free(n); + } + } + + if (status != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_RESULT_STATUS, 0); + if (n == NULL) + return -EBADMSG; + *status = kmip_node_get_enumeration(n); + kmip_node_free(n); + } + + if (reason != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_RESULT_REASON, 0); + *reason = (n == NULL ? 0 : kmip_node_get_enumeration(n)); + kmip_node_free(n); + } + + if (message != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_RESULT_MESSAGE, 0); + *message = (n == NULL ? NULL : + kmip_node_get_text_string(n)); + kmip_node_free(n); + } + + if (async_corr_value != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_ASYNCHRONOUS_CORRELATION_VALUE, + 0); + if (n != NULL) { + *async_corr_value = kmip_node_get_byte_string(n, + async_corr_value_len); + } else { + *async_corr_value = NULL; + if (async_corr_value_len != NULL) + *async_corr_value_len = 0; + } + kmip_node_free(n); + } + + if (payload != NULL) + *payload = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_RESPONSE_PAYLOAD, 0); + + return 0; +} + +/** + * Gets information from a Response Message node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Response Message Yes Structure v1.0 + * Response Header Yes Structure v1.0 + * Batch Item Yes Structure v1.0 + * ... may be repeated + * + * @param node the KMIP node + * @param response_header the response header (can be NULL) + * @param batch_index the index of the response batch item to return + * @param batch_item the batch item (can be NULL) + + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_response(const struct kmip_node *node, + struct kmip_node **response_header, + unsigned int batch_index, + struct kmip_node **batch_item) +{ + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_MESSAGE) + return -EBADMSG; + + if (response_header != NULL) { + *response_header = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_RESPONSE_HEADER, 0); + if (*response_header == NULL) + return -EBADMSG; + } + + if (batch_item != NULL) + *batch_item = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_BATCH_ITEM, + batch_index); + + return 0; +} + +struct kmip_query_info { + enum kmip_query_function query_function; + enum kmip_tag result_tag; + +}; + +static const struct kmip_query_info query_info[] = { + { .query_function = KMIP_QUERY_OPERATIONS, + .result_tag = KMIP_TAG_OPERATION, }, + { .query_function = KMIP_QUERY_OBJECTS, + .result_tag = KMIP_TAG_OBJECT_TYPE, }, + { .query_function = KMIP_QUERY_SERVER_INFORMATION, + .result_tag = KMIP_TAG_VENDOR_IDENTIFICATION, }, + { .query_function = KMIP_QUERY_SERVER_INFORMATION, + .result_tag = KMIP_TAG_SERVER_INFORMATION, }, + { .query_function = KMIP_QUERY_APPLICATION_NAMESPACES, + .result_tag = KMIP_TAG_APPLICATION_NAMESPACE, }, + { .query_function = KMIP_QUERY_EXTENSION_LIST, + .result_tag = KMIP_TAG_EXTENSION_INFORMATION, }, + { .query_function = KMIP_QUERY_EXTENSION_MAP, + .result_tag = KMIP_TAG_EXTENSION_INFORMATION, }, + { .query_function = KMIP_QUERY_ATTESTATION_TYPES, + .result_tag = KMIP_TAG_ATTESTATION_TYPE, }, + { .query_function = KMIP_QUERY_QUERY_RNGS, + .result_tag = KMIP_TAG_RNG_PARAMETERS, }, + { .query_function = KMIP_QUERY_VALIDATIONS, + .result_tag = KMIP_TAG_VALIDATION_INFORMATION, }, + { .query_function = KMIP_QUERY_PROFILES, + .result_tag = KMIP_TAG_PROFILE_INFORMATION, }, + { .query_function = KMIP_QUERY_CAPABILITIES, + .result_tag = KMIP_TAG_CAPABILITY_INFORMATION, }, + { .query_function = KMIP_QUERY_CLIENT_REGISTRATION_METHODS, + .result_tag = KMIP_TAG_CLIENT_REGISTRATION_METHOD, }, + { .query_function = KMIP_QUERY_DEFAULTS_INFORMATION, + .result_tag = KMIP_TAG_DEFAULTS_INFORMATION, }, + { .query_function = KMIP_QUERY_STORAGE_PROTECTION_MASKS, + .result_tag = KMIP_TAG_PROTECTION_STORAGE_MASKS, }, + { .query_function = 0, .result_tag = 0, }, +}; + +/** + * Gets information from a Query response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Operation No Enumeration v1.0 + * ... may be repeated + * Object Type No Enumeration v1.0 + * ... may be repeated + * Vendor Identification No Text String v1.0 + * Server Information No Structure v1.0 + * Application Namespace No Text String v1.0 + * ... may be repeated + * Extension Information No Structure v1.2 + * ... may be repeated + * Attestation Type No Enumeration v1.2 + * ... may be repeated + * RNG Parameters No Structure v1.3 + * ... may be repeated + * Profile Information No Structure v1.3 + * ... may be repeated + * Validation Information No Structure v1.3 + * ... may be repeated + * Capability Information No Structure v1.3 + * ... may be repeated + * Client Registration Method No Enumeration v1.3 + * ... may be repeated + * Defaults Information No Structure v2.0 + * Protection Storage Masks No Structure v2.0 + * + * @param node the KMIP node + * @param query_function the query function to get the results for + * @param num_results On return: the number of result items of the + * specified query function (can be NULL). + * @param result_index the index of the query result item to return + * @param result On return: the query result item of the specified + * query function and index. Function returns -ENOENT + * if no result is available. Can be NULL. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned node is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_query_response_payload(const struct kmip_node *node, + enum kmip_query_function query_function, + unsigned int *num_results, + unsigned int result_index, + struct kmip_node **result) +{ + enum kmip_tag result_tag = 0; + unsigned int i; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + for (i = 0; query_info[i].query_function != 0; i++) { + if (query_info[i].query_function == query_function) { + result_tag = query_info[i].result_tag; + break; + } + } + if (result_tag == 0) + return -EBADMSG; + + if (num_results != NULL) { + *num_results = kmip_node_get_structure_element_by_tag_count( + node, result_tag); + + /* + * KMIP_QUERY_SERVER_INFORMATION may return 2 different result + * tags, count both of them. + */ + if (query_function == KMIP_QUERY_SERVER_INFORMATION) { + *num_results += + kmip_node_get_structure_element_by_tag_count( + node, KMIP_TAG_SERVER_INFORMATION); + } + } + + if (result == NULL) + return 0; + + *result = kmip_node_get_structure_element_by_tag(node, result_tag, + result_index); + if (*result == NULL) { + /* + * KMIP_QUERY_SERVER_INFORMATION may return 2 different result + * tags, return both of them. + */ + if (query_function == KMIP_QUERY_SERVER_INFORMATION) { + if (result_index > 0) + result_index -= 1; + *result = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_SERVER_INFORMATION, + result_index); + if (*result != NULL) + return 0; + } + + return -ENOENT; + } + + return 0; +} + +/** + * Gets information from a Discover Versions response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Protocol Version No Structure v1.2 + * ... may be repeated + * + * @param node the KMIP node + * @param num_versions On return: the number of versions (can be NULL) + * @param index the index of the version item to return + * @param version On return: the version item of the specified + * index. Function returns -ENOENT if no version is + * available at that index. (can be NULL). + * + * @returns 0 on success, or a negative errno in case of an error. + */ +int kmip_get_discover_versions_response_payload(const struct kmip_node *node, + unsigned int *num_versions, + unsigned int index, + struct kmip_version *version) +{ + struct kmip_node *n; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (num_versions != NULL) + *num_versions = kmip_node_get_structure_element_count(node); + + if (version == NULL) + return 0; + + n = kmip_node_get_structure_element_by_index(node, index); + if (n == NULL) + return -ENOENT; + rc = kmip_get_protocol_version(n, version); + kmip_node_free(n); + + return rc; +} + +/** + * Gets information from a Create response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Object Type Yes Enumeration v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Template-Attribute No Structure v1.x only + * + * + * @param node the KMIP node + * @param obj_type the object type of the created object (can be NULL) + * @param unique_id the unique id node (can be NULL) + * @param num_attrs On return: the number of attributes (can be NULL). + * @param attr_index the index of the attribute to get + * @param attributes the attribute (implicitly set by the server) at the + * specified index (as v2.x attributes) (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_create_response_payload(const struct kmip_node *node, + enum kmip_object_type *obj_type, + struct kmip_node **unique_id, + unsigned int *num_attrs, + unsigned int attr_index, + struct kmip_node **attribute) +{ + struct kmip_node *n; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (obj_type != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_OBJECT_TYPE, + 0); + if (n == NULL) + return -EBADMSG; + *obj_type = kmip_node_get_enumeration(n); + kmip_node_free(n); + } + + if (unique_id != NULL) + *unique_id = kmip_node_get_structure_element_by_tag( + node, KMIP_TAG_UNIQUE_IDENTIFIER, 0); + + if (attribute == NULL && num_attrs == NULL) + return 0; + + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_TEMPLATE_ATTRIBUTE, + 0); + if (n == NULL) { + if (num_attrs != NULL) + *num_attrs = 0; + + if (attribute == NULL) + return 0; + + rc = -ENOENT; + goto error; + } + + rc = kmip_get_attributes(n, num_attrs, attr_index, attribute); + kmip_node_free(n); + if (rc != 0) + goto error; + + return 0; + +error: + if (unique_id != NULL) { + kmip_node_free(*unique_id); + *unique_id = NULL; + } + return rc; +} + +/** + * Gets information from a Get Attribute List response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Name Yes Text String v1.x only + * ... may be repeated + * Attribute Reference Yes Enumeration v2.x only + * Structure v2.x only + * ... may be repeated + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * @param num_attr_refs On return: the number of attribute references + * (can be NULL). + * @param index the index of the attribute reference to get + * @param attr_ref the attribute (as v2.x attribute reference) at the + * specified index. Function returns -ENOENT if no + * attribute is available at the index. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_get_attribute_list_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + unsigned int *num_attr_refs, + unsigned int index, + struct kmip_node **attr_ref) +{ + struct kmip_node *n; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (unique_id != NULL) + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, 0); + + if (num_attr_refs != NULL) + *num_attr_refs = + kmip_node_get_structure_element_count(node) - 1; + + if (attr_ref == NULL) + return 0; + + n = kmip_node_get_structure_element_by_index(node, index + 1); + if (n == NULL) { + if (unique_id != NULL) { + kmip_node_free(*unique_id); + *unique_id = NULL; + } + return -ENOENT; + } + + if (kmip_node_get_tag(n) == KMIP_TAG_ATTRIBUTE_REFERENCE) { + /* Its already a KMIP v2.x attribute reference */ + *attr_ref = n; + return 0; + } + + /* Must be a KMIP v1.x attribute name then */ + rc = kmip_get_attribute_name_v1(n, attr_ref); + kmip_node_free(n); + if (rc != 0) { + if (unique_id != NULL) { + kmip_node_free(*unique_id); + *unique_id = NULL; + } + return rc; + } + + return 0; +} + +/** + * Gets information from a Get Attributes response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute No Structure v1.x only + * ... may be repeated + * Attributes Yes Structure v2.x only + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * @param num_attrs On return: the number of attributes (can be NULL). + * @param index the index of the attribute to get + * @param v2_attr the attribute (as v2.x attribute) at the + * specified index. Function returns -ENOENT if no + * attribute is available at the index. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_get_attributes_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + unsigned int *num_attrs, + unsigned int index, + struct kmip_node **v2_attr) +{ + struct kmip_node *attr; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (unique_id != NULL) + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, 0); + + if (v2_attr == NULL && num_attrs == NULL) + return 0; + + attr = kmip_node_get_structure_element_by_index(node, 1); + if (attr == NULL) { + if (num_attrs != NULL) + *num_attrs = 0; + + if (v2_attr == NULL) + return 0; + + rc = -ENOENT; + goto error; + } + + if (kmip_node_get_tag(attr) == KMIP_TAG_ATTRIBUTES) { + /* Its already a KMIP v2.x attributes structure */ + rc = kmip_get_attributes(attr, num_attrs, index, v2_attr); + kmip_node_free(attr); + if (rc != 0) + goto error; + return 0; + } + + /* Must be a KMIP v1.x attribute then */ + kmip_node_free(attr); + + if (num_attrs != NULL) + *num_attrs = kmip_node_get_structure_element_count(node) - 1; + + if (v2_attr == NULL) + return 0; + + attr = kmip_node_get_structure_element_by_index(node, index + 1); + if (attr == NULL) { + rc = -ENOENT; + goto error; + } + + rc = kmip_v2_attr_from_v1_attr(attr, v2_attr); + kmip_node_free(attr); + if (rc != 0) + goto error; + + return 0; + +error: + if (unique_id != NULL) { + kmip_node_free(*unique_id); + *unique_id = NULL; + } + + return rc; +} + +/** + * Gets information from a response payload node that include a unique id and + * an attribute. + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Yes Structure v1.x only + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * @param v2_attr the added attribute (as v2.x attribute). + * For KMIP v1.y no attribute is returned. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +static int kmip_get_unique_id_attribute_response_payload( + const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **v2_attr) +{ + struct kmip_node *attr; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (unique_id != NULL) + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, 0); + + if (v2_attr == NULL) + return 0; + + /* KMIP v2.x does not send a attribute in the reply, but v1.x does */ + attr = kmip_node_get_structure_element_by_tag(node, KMIP_TAG_ATTRIBUTE, + 0); + if (attr == NULL) { + + *v2_attr = NULL; + return 0; + } + + rc = kmip_v2_attr_from_v1_attr(attr, v2_attr); + kmip_node_free(attr); + if (rc != 0) + goto error; + + return 0; + +error: + if (unique_id != NULL) { + kmip_node_free(*unique_id); + *unique_id = NULL; + } + + return rc; +} + + +/** + * Gets information from a Add Attribute response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Yes Structure v1.x only + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * @param v2_attr the added attribute (as v2.x attribute). + * For KMIP v1.y no attribute is returned. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_add_attribute_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **v2_attr) +{ + return kmip_get_unique_id_attribute_response_payload(node, unique_id, + v2_attr); +} + +/** + * Gets information from a Modify Attribute response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Yes Structure v1.x only + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * @param v2_attr the modified attribute (as v2.x attribute). + * For KMIP v1.y no attribute is returned. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_modify_attribute_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **v2_attr) +{ + return kmip_get_unique_id_attribute_response_payload(node, unique_id, + v2_attr); +} + +/** + * Gets information from a Set Attribute response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * KMIP v1.x does not have a Set Attribute operation. + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_set_attribute_v2_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id) +{ + return kmip_get_unique_id_attribute_response_payload(node, unique_id, + NULL); +} + +/** + * Gets information from a Delete Attribute response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Attribute Yes Structure v1.x only + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * @param v2_attr the modified attribute (as v2.x attribute). + * For KMIP v1.y no attribute is returned. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_delete_attribute_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + struct kmip_node **v2_attr) +{ + return kmip_get_unique_id_attribute_response_payload(node, unique_id, + v2_attr); +} + +/** + * Gets information from a response payload node that only includes a unique id: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +static int kmip_get_unique_id_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id) +{ + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (unique_id != NULL) + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, 0); + + return 0; +} + +/** + * Gets information from a Activate response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_activate_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id) +{ + return kmip_get_unique_id_response_payload(node, unique_id); +} + +/** + * Gets information from a Destroy response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_destroy_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id) +{ + return kmip_get_unique_id_response_payload(node, unique_id); +} + +/** + * Gets information from a Archive response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_archive_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id) +{ + return kmip_get_unique_id_response_payload(node, unique_id); +} + +/** + * Gets information from a Recover response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_recover_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id) +{ + return kmip_get_unique_id_response_payload(node, unique_id); +} + +/** + * Gets information from a Revoke response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * + * @param node the KMIP node + * @param unique_id the unique id node (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_revoke_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id) +{ + return kmip_get_unique_id_response_payload(node, unique_id); +} + +/** + * Gets information from a Locate response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Located Items No Integer v2.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * ... may be repated + * + * @param node the KMIP node + * @param located_items On return: the total number of located items. + * Only available since KMIP v2.x. If not available, + * it is returned as -1. May be NULL. + * @param num_items On return: the returned number of located items. + * May be NULL. + * @param index The index of the returned item. + * @param unique_id the unique id node at the specified index. + * Function returns -ENOENT if no item is available at + * the index. May be NULL. + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_locate_response_payload(const struct kmip_node *node, + int32_t *located_items, + unsigned int *num_items, + unsigned int index, + struct kmip_node **unique_id) +{ + struct kmip_node *n; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (located_items != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_LOCATED_ITEMS, 0); + *located_items = (n != NULL ? kmip_node_get_integer(n) : -1); + kmip_node_free(n); + } + + if (num_items != NULL) + *num_items = kmip_node_get_structure_element_by_tag_count(node, + KMIP_TAG_UNIQUE_IDENTIFIER); + + if (unique_id != NULL) { + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, index); + if (*unique_id == NULL) + return -ENOENT; + } + + return 0; +} + +/** + * Gets information from a Register response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Template-Attribute No Structure v1.x only + * + * + * @param node the KMIP node + * @param obj_type the object type of the created object (can be NULL) + * @param unique_id the unique id node (can be NULL) + * @param num_attrs On return: the number of attributes (can be NULL). + * @param attr_index the index of the attribute to get + * @param attributes the attribute (implicitly set by the server) at the + * specified index (as v2.x attributes) (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_register_response_payload(const struct kmip_node *node, + struct kmip_node **unique_id, + unsigned int *num_attrs, + unsigned int attr_index, + struct kmip_node **attribute) +{ + struct kmip_node *attrs; + int rc; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (unique_id != NULL) + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, 0); + + if (attribute == NULL && num_attrs == NULL) + return 0; + + attrs = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_TEMPLATE_ATTRIBUTE, 0); + if (attrs == NULL) { + if (num_attrs != NULL) + *num_attrs = 0; + + if (attribute == NULL) + return 0; + + rc = -ENOENT; + goto error; + } + + rc = kmip_get_attributes(attrs, num_attrs, attr_index, attribute); + kmip_node_free(attrs); + if (rc != 0) + goto error; + + return 0; + +error: + if (unique_id != NULL) { + kmip_node_free(*unique_id); + *unique_id = NULL; + } + return rc; +} + +/** + * Gets information from a Get response payload node: + * + * Object Required Encoding KMIP version + * --------------------------------------------------------------------- + * Payload Yes Structure v1.0 + * Object Type Yes Enumeration v1.0 + * Unique Identifier Yes Text String v1.0 + * Enumeration v2.0 + * Integer v2.0 + * Yes Structure v1.0 + * + * @param node the KMIP node + * @param obj_type the object type of the created object (can be NULL) + * @param unique_id the unique id node (can be NULL) + * @param object the object (can be NULL) + * + * @returns 0 on success, or a negative errno in case of an error. + * The reference count of the returned nodes is increased. The caller must + * free the node via kmip_node_free() when no longer needed. + */ +int kmip_get_get_response_payload(const struct kmip_node *node, + enum kmip_object_type *obj_type, + struct kmip_node **unique_id, + struct kmip_node **object) +{ + struct kmip_node *n; + int rc = 0; + + if (node == NULL) + return -EINVAL; + + if (kmip_node_get_tag(node) != KMIP_TAG_RESPONSE_PAYLOAD) + return -EBADMSG; + + if (obj_type != NULL) { + n = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_OBJECT_TYPE, + 0); + if (n == NULL) + return -EBADMSG; + *obj_type = kmip_node_get_enumeration(n); + kmip_node_free(n); + } + + if (unique_id != NULL) { + *unique_id = kmip_node_get_structure_element_by_tag(node, + KMIP_TAG_UNIQUE_IDENTIFIER, 0); + if (*unique_id == NULL) + return -EBADMSG; + } + + if (object == NULL) + return 0; + + *object = kmip_node_get_structure_element_by_index(node, 2); + if (*object == NULL) { + rc = -EBADMSG; + goto error; + } + + switch (kmip_node_get_tag(*object)) { + case KMIP_TAG_CERTIFICATE: + case KMIP_TAG_CERTIFICATE_REQUEST: + case KMIP_TAG_OPAQUE_OBJECT: + case KMIP_TAG_PGP_KEY: + case KMIP_TAG_PRIVATE_KEY: + case KMIP_TAG_PUBLIC_KEY: + case KMIP_TAG_SECRET_DATA: + case KMIP_TAG_SYMMETRIC_KEY: + break; + default: + kmip_node_free(*object); + *object = NULL; + rc = -EBADMSG; + goto error; + } + + return 0; + +error: + if (*unique_id != NULL) { + kmip_node_free(*unique_id); + *unique_id = NULL; + } + return rc; +} diff --git a/libkmipclient/tls.c b/libkmipclient/tls.c new file mode 100644 index 00000000..4bd84e88 --- /dev/null +++ b/libkmipclient/tls.c @@ -0,0 +1,528 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "kmip.h" +#include "utils.h" + +#ifndef OPENSSL_VERSION_PREREQ + #if defined(OPENSSL_VERSION_MAJOR) && defined(OPENSSL_VERSION_MINOR) + #define OPENSSL_VERSION_PREREQ(maj, min) \ + ((OPENSSL_VERSION_MAJOR << 16) + \ + OPENSSL_VERSION_MINOR >= ((maj) << 16) + (min)) + #else + #define OPENSSL_VERSION_PREREQ(maj, min) \ + (OPENSSL_VERSION_NUMBER >= (((maj) << 28) | \ + ((min) << 20))) + #endif +#endif + +/** + * Verify the pinned public key of the server of a plain TLS KMIP connection + * + * @param conn the KMIP connection to free + * @param cert_pubkey the server certificate's public key + * @param debug if true, debug messages are printed + */ +static int kmip_connection_tls_verify_pinned_pubkey( + struct kmip_connection *conn, + EVP_PKEY *cert_pubkey, bool debug) +{ + EVP_PKEY *pinned_key = NULL; + int rc = 0; + FILE *fp; + + fp = fopen(conn->config.tls_pinned_pubkey, "r"); + if (fp == NULL) { + rc = -errno; + kmip_debug(debug, "Failed to read pinned public key '%s': %s", + conn->config.tls_pinned_pubkey, strerror(-rc)); + return rc; + } + + pinned_key = PEM_read_PUBKEY(fp, NULL, NULL, NULL); + fclose(fp); + + if (pinned_key == NULL) { + kmip_debug(debug, "PEM_read_PUBKEY failed: '%s'", + conn->config.tls_pinned_pubkey); + if (debug) + ERR_print_errors_fp(stderr); + return -EIO; + } + +#if !OPENSSL_VERSION_PREREQ(3, 0) + if (EVP_PKEY_cmp(pinned_key, cert_pubkey) != 1) { +#else + if (EVP_PKEY_eq(pinned_key, cert_pubkey) != 1) { +#endif + kmip_debug(debug, "Server public key does not match the pinned " + "public key '%s'", conn->config.tls_pinned_pubkey); + rc = -EPERM; + } + + EVP_PKEY_free(pinned_key); + + return rc; +} + +/** + * Verify the pinned server certificate key of the server of a plain TLS KMIP + * connection + * + * @param conn the KMIP connection to free + * @param server_cert the server certificate + * @param debug if true, debug messages are printed + */ +static int kmip_connection_tls_verify_pinned_cert( + struct kmip_connection *conn, + X509 *server_cert, bool debug) +{ + X509 *pinned_cert = NULL; + int rc = 0; + FILE *fp; + + fp = fopen(conn->config.tls_server_cert, "r"); + if (fp == NULL) { + rc = -errno; + kmip_debug(debug, "Failed to read pinned server cert: %s", + conn->config.tls_server_cert, strerror(-rc)); + return rc; + } + + pinned_cert = PEM_read_X509(fp, NULL, NULL, NULL); + fclose(fp); + + if (pinned_cert == NULL) { + kmip_debug(debug, "PEM_read_X509 failed: '%s'", + conn->config.tls_server_cert); + if (debug) + ERR_print_errors_fp(stderr); + return -EIO; + } + + if (X509_cmp(pinned_cert, server_cert) != 0) { + kmip_debug(debug, "Server certificate does not match the " + "pinned certificate '%s'", + conn->config.tls_server_cert); + rc = -EPERM; + } + + X509_free(pinned_cert); + + return rc; +} + +/** + * Verify the issuer certificate key of the server of a plain TLS KMIP + * connection + * + * @param conn the KMIP connection to free + * @param server_cert the server certificate + * @param debug if true, debug messages are printed + */ +static int kmip_connection_tls_verify_issuer_cert( + struct kmip_connection *conn, + X509 *server_cert, bool debug) +{ + X509 *issuer_cert = NULL; + int rc = 0; + FILE *fp; + + fp = fopen(conn->config.tls_issuer_cert, "r"); + if (fp == NULL) { + rc = -errno; + kmip_debug(debug, "Failed to read issuer cert '%s': %s", + conn->config.tls_issuer_cert, strerror(-rc)); + return rc; + } + + issuer_cert = PEM_read_X509(fp, NULL, NULL, NULL); + fclose(fp); + + if (issuer_cert == NULL) { + kmip_debug(debug, "PEM_read_X509 failed: '%s'", + conn->config.tls_issuer_cert); + if (debug) + ERR_print_errors_fp(stderr); + return -EIO; + } + + if (X509_check_issued(issuer_cert, server_cert) != X509_V_OK) { + kmip_debug(debug, "The server certificate was not issued by " + "certificate '%s'", conn->config.tls_issuer_cert); + rc = -EPERM; + } + + X509_free(issuer_cert); + + return rc; +} + +/** + * Verify the server of a plain TLS KMIP connection + * + * @param conn the KMIP connection to free + * @param debug if true, debug messages are printed + */ +static int kmip_connection_tls_verify_server(struct kmip_connection *conn, + bool debug) +{ + X509 *server_cert; + int rc; + + server_cert = SSL_get_peer_certificate(conn->plain_tls.ssl); + if (server_cert == NULL) { + kmip_debug(debug, "SSL_get_peer_certificate failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + + if (conn->config.tls_issuer_cert != NULL) { + rc = kmip_connection_tls_verify_issuer_cert(conn, server_cert, + debug); + if (rc != 0) { + kmip_debug(debug, + "kmip_connection_tls_verify_issuer_cert " + "failed"); + goto out; + } + } + + if (conn->config.tls_server_cert != NULL) { + rc = kmip_connection_tls_verify_pinned_cert(conn, server_cert, + debug); + if (rc != 0) { + kmip_debug(debug, + "kmip_connection_tls_verify_pinned_cert " + "failed"); + goto out; + } + } + + if (conn->config.tls_pinned_pubkey != NULL) { + rc = kmip_connection_tls_verify_pinned_pubkey(conn, + X509_get0_pubkey(server_cert), + debug); + if (rc != 0) { + kmip_debug(debug, + "kmip_connection_tls_pinned_pubkey failed"); + goto out; + } + } + + rc = 0; + +out: + if (server_cert != NULL) + X509_free(server_cert); + + return 0; +} + +/** + * Initializes a new plain TLS connection to a KMIP server. + * + * @param conn The KMIP connection + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_connection_tls_init(struct kmip_connection *conn, bool debug) +{ + char *hostname = NULL, *port = NULL, *tok; + struct stat sb; + int rc; + + if (conn == NULL) + return -EINVAL; + + conn->plain_tls.ssl_ctx = SSL_CTX_new(TLS_client_method()); + if (conn->plain_tls.ssl_ctx == NULL) { + kmip_debug(debug, "SSL_CTX_new failed"); + if (debug) + ERR_print_errors_fp(stderr); + return -EIO; + } + + if (SSL_CTX_use_certificate_file(conn->plain_tls.ssl_ctx, + conn->config.tls_client_cert, + SSL_FILETYPE_PEM) != 1) { + kmip_debug(debug, "Loading the client certificate from '%s' " + "failed", conn->config.tls_client_cert); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + + if (SSL_CTX_use_PrivateKey(conn->plain_tls.ssl_ctx, + conn->config.tls_client_key) != 1) { + kmip_debug(debug, "Setting the client key from PKEY %p " + "failed", conn->config.tls_client_key); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + + } + + if (conn->config.tls_ca != NULL) { + if (stat(conn->config.tls_ca, &sb) != 0) { + rc = -errno; + kmip_debug(debug, "stat failed on '%s': %s", + conn->config.tls_ca, strerror(-rc)); + goto out; + } + + if (S_ISDIR(sb.st_mode)) { + if (SSL_CTX_load_verify_locations( + conn->plain_tls.ssl_ctx, NULL, + conn->config.tls_ca) != 1) { + kmip_debug(debug, "Setting the verify location " + "to '%s' failed", + conn->config.tls_ca); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + } else { + if (SSL_CTX_load_verify_locations( + conn->plain_tls.ssl_ctx, + conn->config.tls_ca, NULL) != 1) { + kmip_debug(debug, "Setting the verify location " + "to '%s' failed", + conn->config.tls_ca); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + } + } + + conn->plain_tls.bio = + BIO_new_buffer_ssl_connect(conn->plain_tls.ssl_ctx); + if (conn->plain_tls.bio == NULL) { + kmip_debug(debug, "BIO_new_ssl_connect failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + + BIO_get_ssl(conn->plain_tls.bio, &conn->plain_tls.ssl); + if (conn->plain_tls.ssl == NULL) { + kmip_debug(debug, "BIO_get_ssl failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + + hostname = strdup(conn->config.server); + if (hostname == NULL) { + kmip_debug(debug, "strdup failed"); + rc = -ENOMEM; + goto out; + } + + /* Split port number from hostname, if specified */ + if (hostname[0] == '[') { + /* IPv6 address enclosed in square brackets */ + tok = strchr(hostname, ']'); + if (tok == NULL) { + kmip_debug(debug, "malformed IPv6 address"); + rc = -EINVAL; + free(hostname); + goto out; + } + tok++; + if (*tok == ':') { + port = tok + 1; + *tok = 0; + } + } else { + /* hostname or IPv4 address */ + tok = strchr(hostname, ':'); + if (tok != NULL) { + port = tok + 1; + *tok = 0; + } + } + + kmip_debug(debug, "hostname: '%s'", hostname); + if (port == NULL) { + port = KMIP_DEFAULT_PLAIN_TLS_PORT; + kmip_debug(debug, "port: default (%s)", port); + } else { + kmip_debug(debug, "port: %s", port); + } + + if (conn->config.tls_verify_host) { + SSL_set_hostflags(conn->plain_tls.ssl, + X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS); + if (SSL_set1_host(conn->plain_tls.ssl, hostname) != 1) { + kmip_debug(debug, "SSL_set1_host failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + } + + SSL_set_verify(conn->plain_tls.ssl, (conn->config.tls_verify_peer || + conn->config.tls_verify_host) ? + SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); + + if (conn->config.tls_cipher_list != NULL) { + if (SSL_set_cipher_list(conn->plain_tls.ssl, + conn->config.tls_cipher_list) != 1) { + kmip_debug(debug, "SSL_set_cipher_list failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + } + + if (conn->config.tls13_cipher_list != NULL) { + if (SSL_set_ciphersuites(conn->plain_tls.ssl, + conn->config.tls13_cipher_list) != 1) { + kmip_debug(debug, "SSL_set_ciphersuites failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + } + + SSL_set_mode(conn->plain_tls.ssl, SSL_MODE_AUTO_RETRY); + + BIO_set_conn_hostname(conn->plain_tls.bio, hostname); + BIO_set_conn_port(conn->plain_tls.bio, port); + + if (BIO_do_connect(conn->plain_tls.bio) != 1) { + kmip_debug(debug, "BIO_do_connect failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + + kmip_debug(debug, "TLS connection established using %s", + SSL_get_cipher_name(conn->plain_tls.ssl)); + + rc = kmip_connection_tls_verify_server(conn, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_connection_tls_verify_server failed"); + if (debug) + ERR_print_errors_fp(stderr); + rc = -EIO; + goto out; + } + + rc = 0; + +out: + if (rc != 0) + kmip_connection_tls_term(conn); + if (hostname != NULL) + free(hostname); + + return rc; +} + +/** + * Perform a request over the KMIP connection + * + * @param conn n the KMIP connection + * @param request the request to send + * @param response On return: the received response. Must be freed by + * the caller. + * + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_connection_tls_perform(struct kmip_connection *conn, + struct kmip_node *request, + struct kmip_node **response, + bool debug) +{ + size_t size; + int rc; + + if (conn == NULL || request == NULL || response == NULL) + return -EINVAL; + + *response = NULL; + + /* Send out the request */ + rc = kmip_encode_ttlv(request, conn->plain_tls.bio, &size, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_ttlv failed"); + goto out; + } + if (BIO_flush(conn->plain_tls.bio) != 1) { + kmip_debug(debug, "BIO_flush failed"); + goto out; + } + kmip_debug(debug, "%lu bytes sent", size); + + /* receive the response */ + rc = kmip_decode_ttlv(conn->plain_tls.bio, NULL, response, debug); + if (rc != 0 || *response == NULL) { + kmip_debug(debug, "kmip_decode_ttlv failed"); + goto out; + } + + rc = 0; + +out: + if (rc != 0) { + if (BIO_reset(conn->plain_tls.bio) != 1) + kmip_debug(debug, "BIO_reset failed"); + } + + return rc; +} + +/** + * Terminates a plain TLS KMIP connection. + * + * @param conn the KMIP connection to free + */ +void kmip_connection_tls_term(struct kmip_connection *conn) +{ + if (conn == NULL) + return; + + if (conn->plain_tls.bio != NULL) { + BIO_ssl_shutdown(conn->plain_tls.bio); + BIO_free_all(conn->plain_tls.bio); + } + if (conn->plain_tls.ssl_ctx != NULL) + SSL_CTX_free(conn->plain_tls.ssl_ctx); + + conn->plain_tls.bio = NULL; + conn->plain_tls.ssl_ctx = NULL; + conn->plain_tls.ssl = NULL; +} diff --git a/libkmipclient/ttlv.c b/libkmipclient/ttlv.c new file mode 100644 index 00000000..9c6702b1 --- /dev/null +++ b/libkmipclient/ttlv.c @@ -0,0 +1,511 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include +#include + +#include "kmip.h" +#include "utils.h" + +#define KMIP_TTLV_HEADER_LENGTH 8 +#define KMIP_TTLV_BLOCK_LENGTH 8 + +/** + * Decode a KMIP node from the data in BIO using the TTLV encoding. + * + * @param bio the OpenSSL bio to read the data from + * @param size Optional: If not NULL: + * On entry: The number of bytes available to read + * On return: decremented by the number of bytes read + * If NULL, it is assumed that we can read from bio + * as many bytes as needed. + * @param node On return: the decoded node. The newly allocated + * node has a reference count of 1. + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_decode_ttlv(BIO *bio, size_t *size, struct kmip_node **node, + bool debug) +{ + unsigned char padding[KMIP_TTLV_BLOCK_LENGTH]; + unsigned char ttlv[KMIP_TTLV_HEADER_LENGTH]; + size_t value_len, pad_len; + struct kmip_node *n, *e; + void *value = NULL; + uint32_t int32; + uint64_t int64; + int rc; + + if (bio == NULL || node == NULL) + return -EINVAL; + + if (size != NULL) + kmip_debug(debug, "size: %lu", *size); + else + kmip_debug(debug, "size: unknown"); + + if (size != NULL && *size < sizeof(ttlv)) { + kmip_debug(debug, "length %u > available size %lu", + sizeof(ttlv), *size); + return -EMSGSIZE; + } + + if (BIO_read(bio, ttlv, sizeof(ttlv)) != sizeof(ttlv)) { + kmip_debug(debug, "BIO_read failed"); + return -EIO; + } + if (size != NULL) + *size -= sizeof(ttlv); + + n = calloc(1, sizeof(struct kmip_node)); + if (n == NULL) { + kmip_debug(debug, "calloc failed"); + return -ENOMEM; + } + n->ref_count = 1; + + /* Tag: 3-byte binary unsigned integer, transmitted big endian */ + n->tag |= (uint32_t)(ttlv[0] << 16); + n->tag |= (uint32_t)(ttlv[1] << 8); + n->tag |= (uint32_t)(ttlv[2]); + + /* Type: 1 byte containing a coded value that indicates the data type */ + n->type = ttlv[3]; + + /* Length: 32-bit binary integer, transmitted big-endian */ + n->length |= (uint32_t)(ttlv[4] << 24); + n->length |= (uint32_t)(ttlv[5] << 16); + n->length |= (uint32_t)(ttlv[6] << 8); + n->length |= (uint32_t)(ttlv[7]); + + kmip_debug(debug, "tag: 0x%x type: 0x%x, length: %u", n->tag, n->type, + n->length); + + switch (n->type) { + case KMIP_TYPE_STRUCTURE: + value_len = n->length; + break; + + case KMIP_TYPE_BIG_INTEGER: + case KMIP_TYPE_TEXT_STRING: + case KMIP_TYPE_BYTE_STRING: + value_len = n->length; + value = calloc(1, value_len + 1); + if (value == NULL) { + kmip_debug(debug, "calloc failed"); + rc = -ENOMEM; + goto out; + } + break; + + case KMIP_TYPE_INTEGER: + case KMIP_TYPE_ENUMERATION: + case KMIP_TYPE_INTERVAL: + value_len = sizeof(int32); + value = &int32; + break; + + case KMIP_TYPE_LONG_INTEGER: + case KMIP_TYPE_BOOLEAN: + case KMIP_TYPE_DATE_TIME: + case KMIP_TYPE_DATE_TIME_EXTENDED: + value_len = sizeof(int64); + value = &int64; + break; + + default: + kmip_debug(debug, "unknown type: 0x%x", n->type); + rc = -EBADMSG; + goto out; + } + + if (n->length != value_len) { + kmip_debug(debug, "length %u not as expected (%lu)", n->length, + value_len); + rc = -EBADMSG; + goto out; + } + if (size != NULL && *size < n->length) { + kmip_debug(debug, "length %u > available size %lu", n->length, + *size); + rc = -EMSGSIZE; + goto out; + } + + if (n->type != KMIP_TYPE_STRUCTURE && value_len > 0) { + if (BIO_read(bio, value, value_len) != (int)value_len) { + kmip_debug(debug, "BIO_read failed"); + rc = -EIO; + goto out; + } + } + if (size != NULL) + *size -= value_len; + + if ((value_len % KMIP_TTLV_BLOCK_LENGTH) != 0) { + pad_len = KMIP_TTLV_BLOCK_LENGTH - + (value_len % KMIP_TTLV_BLOCK_LENGTH); + + kmip_debug(debug, "pad_len: %lu", pad_len); + if (BIO_read(bio, padding, pad_len) != (int)pad_len) { + kmip_debug(debug, "BIO_read failed (padding)"); + rc = -EIO; + goto out; + } + if (size != NULL) + *size -= pad_len; + } + + switch (n->type) { + case KMIP_TYPE_STRUCTURE: + while (value_len > 0) { + rc = kmip_decode_ttlv(bio, &value_len, &e, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_decode_ttlv failed: " + "rc: %d", rc); + goto out; + } + rc = kmip_node_add_structure_element(n, e); + kmip_node_free(e); + if (rc != 0) { + kmip_debug(debug, + "kmip_node_structure_add_element " + "failed: rc: %d", rc); + goto out; + } + } + break; + + case KMIP_TYPE_INTEGER: + n->integer_value = be32toh(int32); + break; + + case KMIP_TYPE_LONG_INTEGER: + n->long_value = be64toh(int64); + break; + + case KMIP_TYPE_BIG_INTEGER: + rc = kmip_decode_bignum(value, value_len, + &n->big_integer_value); + if (rc != 0) { + kmip_debug(debug, "kmip_decode_bignum failed"); + goto out; + } + free(value); + value = NULL; + break; + + case KMIP_TYPE_ENUMERATION: + n->enumeration_value = be32toh(int32); + break; + + case KMIP_TYPE_BOOLEAN: + n->boolean_value = int64 != 0; + break; + + case KMIP_TYPE_TEXT_STRING: + n->text_value = value; + break; + + case KMIP_TYPE_BYTE_STRING: + n->bytes_value = value; + break; + + case KMIP_TYPE_DATE_TIME: + n->date_time_value = be64toh(int64); + break; + + case KMIP_TYPE_INTERVAL: + n->interval_value = be32toh(int32); + break; + + case KMIP_TYPE_DATE_TIME_EXTENDED: + n->date_time_ext_value = be64toh(int64); + break; + + default: + kmip_debug(debug, "unknown type: 0x%x", n->type); + rc = -EBADMSG; + goto out; + } + + *node = n; + rc = 0; + +out: + if (rc != 0) { + switch (n->type) { + case KMIP_TYPE_BIG_INTEGER: + case KMIP_TYPE_TEXT_STRING: + case KMIP_TYPE_BYTE_STRING: + free(value); + break; + default: + break; + } + + kmip_node_free(n); + } + return rc; +} + +/** + * Gets the length of the value part of a KMIP node (in TTLV encoding) + */ +static int kmip_node_get_length(struct kmip_node *node, size_t *length) +{ + struct kmip_node *element; + size_t len; + int rc; + + if (node == NULL || length == NULL) + return -EINVAL; + + switch (node->type) { + case KMIP_TYPE_STRUCTURE: + *length = 0; + element = node->structure_value; + while (element != NULL) { + rc = kmip_node_get_length(element, &len); + if (rc != 0) + return rc; + + *length += KMIP_TTLV_HEADER_LENGTH + len; + if ((len % KMIP_TTLV_BLOCK_LENGTH) != 0) + *length += KMIP_TTLV_BLOCK_LENGTH - + (len % KMIP_TTLV_BLOCK_LENGTH); + + element = element->next; + } + break; + + case KMIP_TYPE_INTEGER: + case KMIP_TYPE_ENUMERATION: + case KMIP_TYPE_INTERVAL: + *length = sizeof(int32_t); + break; + + case KMIP_TYPE_LONG_INTEGER: + case KMIP_TYPE_BOOLEAN: + case KMIP_TYPE_DATE_TIME: + case KMIP_TYPE_DATE_TIME_EXTENDED: + *length = sizeof(int64_t); + break; + + case KMIP_TYPE_BIG_INTEGER: + *length = kmip_encode_bignum_length(node->big_integer_value); + /* BIG INTEGERS must be a multiple of 8 bytes long */ + if ((*length % KMIP_BIG_INTEGER_BLOCK_LENGTH) != 0) + *length += KMIP_BIG_INTEGER_BLOCK_LENGTH - + (*length % KMIP_BIG_INTEGER_BLOCK_LENGTH); + break; + + case KMIP_TYPE_BYTE_STRING: + *length = node->length; + break; + + case KMIP_TYPE_TEXT_STRING: + if (node->text_value != NULL) + *length = strlen(node->text_value); + else + *length = 0; + break; + + default: + return -EINVAL; + } + + return 0; +} + +/** + * Encode a KMIP node into a BIO using the TTLV encoding. + * + * @param node the node to encode + * @param bio the OpenSSL bio to write the data to + * @param size On return: the number of bytes written to BIO + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_encode_ttlv(struct kmip_node *node, BIO *bio, size_t *size, + bool debug) +{ + const unsigned char padding[KMIP_TTLV_BLOCK_LENGTH] = { 0 }; + unsigned char ttlv[KMIP_TTLV_HEADER_LENGTH]; + size_t len, elem_len, value_len, pad_len; + struct kmip_node *element; + void *value = NULL; + uint32_t int32; + uint64_t int64; + int rc; + + if (bio == NULL || node == NULL || size == NULL) + return -EINVAL; + + kmip_debug(debug, "tag: 0x%x type: 0x%x, length: %u", node->tag, + node->type, node->length); + + *size = 0; + + /* Update node's length field to match node's current data */ + rc = kmip_node_get_length(node, &len); + if (rc != 0) { + kmip_debug(debug, "kmip_node_get_length failed"); + return rc; + } + node->length = len; + + /* Tag: 3-byte binary unsigned integer, transmitted big endian */ + ttlv[0] = (node->tag & 0xff0000) >> 16; + ttlv[1] = (node->tag & 0xff00) >> 8; + ttlv[2] = (node->tag & 0xff); + + /* Type: 1 byte containing a coded value that indicates the data type */ + ttlv[3] = node->type; + + /* Length: 32-bit binary integer, transmitted big-endian */ + ttlv[4] = (node->length & 0xff000000) >> 24; + ttlv[5] = (node->length & 0xff0000) >> 16; + ttlv[6] = (node->length & 0xff00) >> 8; + ttlv[7] = (node->length & 0xff); + + if (BIO_write(bio, ttlv, sizeof(ttlv)) != sizeof(ttlv)) { + kmip_debug(debug, "BIO_write failed"); + return -EIO; + } + *size += sizeof(ttlv); + + switch (node->type) { + case KMIP_TYPE_STRUCTURE: + value_len = 0; + element = node->structure_value; + while (element != NULL) { + rc = kmip_encode_ttlv(element, bio, &elem_len, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_ttlv failed"); + return rc; + } + value_len += elem_len; + element = element->next; + } + if (value_len != node->length) { + kmip_debug(debug, "written length %lu not as expected " + "(%u)", len, node->length); + return -EIO; + } + break; + + case KMIP_TYPE_INTEGER: + int32 = htobe32(node->integer_value); + value_len = sizeof(int32); + value = &int32; + break; + + case KMIP_TYPE_LONG_INTEGER: + int64 = htobe64(node->long_value); + value_len = sizeof(int64); + value = &int64; + break; + + case KMIP_TYPE_BIG_INTEGER: + value_len = node->length; /* was already calculated above */ + value = malloc(value_len); + if (value == NULL) { + kmip_debug(debug, "malloc failed"); + return -ENOMEM; + } + rc = kmip_encode_bignum(node->big_integer_value, value, + value_len); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_bignum failed"); + goto out; + } + break; + + case KMIP_TYPE_ENUMERATION: + int32 = htobe32(node->enumeration_value); + value_len = sizeof(int32); + value = &int32; + break; + + case KMIP_TYPE_BOOLEAN: + int64 = node->boolean_value ? 1 : 0; + value_len = sizeof(int64); + value = &int64; + break; + + case KMIP_TYPE_TEXT_STRING: + value_len = node->length; + value = node->text_value; + break; + + case KMIP_TYPE_BYTE_STRING: + value_len = node->length; + value = node->bytes_value; + break; + + case KMIP_TYPE_DATE_TIME: + int64 = htobe64(node->date_time_value); + value_len = sizeof(int64); + value = &int64; + break; + + case KMIP_TYPE_INTERVAL: + int32 = htobe32(node->interval_value); + value_len = sizeof(int32); + value = &int32; + break; + + case KMIP_TYPE_DATE_TIME_EXTENDED: + int64 = htobe64(node->date_time_ext_value); + value_len = sizeof(int64); + value = &int64; + break; + + default: + kmip_debug(debug, "unknown type: 0x%x", node->type); + return -EINVAL; + } + + if (value != NULL) { + if (BIO_write(bio, value, value_len) != (int)value_len) { + kmip_debug(debug, "BIO_write failed"); + rc = -EIO; + goto out; + } + + } + *size += value_len; + + if ((value_len % KMIP_TTLV_BLOCK_LENGTH) != 0) { + pad_len = KMIP_TTLV_BLOCK_LENGTH - + (value_len % KMIP_TTLV_BLOCK_LENGTH); + + kmip_debug(debug, "pad_len: %lu", pad_len); + if (BIO_write(bio, padding, pad_len) != (int)pad_len) { + kmip_debug(debug, "BIO_write failed (padding)"); + rc = -EIO; + goto out; + } + *size += pad_len; + } + + kmip_debug(debug, "size: %lu", *size); + + rc = 0; +out: + if (node->type == KMIP_TYPE_BIG_INTEGER) + free(value); + + return rc; +} + diff --git a/libkmipclient/utils.c b/libkmipclient/utils.c new file mode 100644 index 00000000..4a88d0c5 --- /dev/null +++ b/libkmipclient/utils.c @@ -0,0 +1,726 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#define _XOPEN_SOURCE +#define _DEFAULT_SOURCE + +#include +#include +#include +#include +#include + +#include "utils.h" +#include "names.h" + +/** + * Print a debug message + */ +void kmip_print_debug(const char *func, const char *fmt, ...) +{ + char tmp_fmt[200]; + va_list ap; + + if (snprintf(tmp_fmt, sizeof(tmp_fmt), "DBG: %s: %s", func, fmt) > + (int)sizeof(tmp_fmt)) + return; + + va_start(ap, fmt); + vwarnx(tmp_fmt, ap); + va_end(ap); +} + + +/** + * Parse a decimal string into a 64 bit signed value + */ +int kmip_parse_decimal_int(const char *str, int64_t *val) +{ + long long v; + char *endptr; + + if (str == NULL) + return -EINVAL; + + errno = 0; + v = strtoll(str, &endptr, 10); + + if ((errno == ERANGE && (v == LLONG_MAX || v == LLONG_MIN)) || + (errno != 0 && v == 0)) + return -EBADMSG; + + if (endptr == str || *endptr != 0) + return -EBADMSG; + + *val = v; + return 0; +} + +/** + * Parse a decimal string into a 64 bit unsigned value + */ +int kmip_parse_decimal_uint(const char *str, uint64_t *val) +{ + unsigned long long v; + char *endptr; + + if (str == NULL) + return -EINVAL; + + errno = 0; + v = strtoull(str, &endptr, 10); + + if ((errno == ERANGE && (v == 0 || v == ULLONG_MAX)) || + (errno != 0 && v == 0)) + return -EBADMSG; + + if (endptr == str || *endptr != 0) + return -EBADMSG; + + *val = v; + return 0; +} + +/** + * Parse a hex string into a 64 bit signed value + */ +int kmip_parse_hex_int(const char *str, int64_t *val) +{ + long long v; + char *endptr; + + if (str == NULL) + return -EINVAL; + + if (strncmp(str, "0x", 2) != 0) + return -EBADMSG; + + errno = 0; + v = strtoll(str, &endptr, 16); + + if ((errno == ERANGE && (v == LLONG_MAX || v == LLONG_MIN)) || + (errno != 0 && v == 0)) + return -EBADMSG; + + if (endptr == str || *endptr != 0) + return -EBADMSG; + + *val = v; + return 0; +} + +/** + * Parse a hex string into a variable length signed big integer. + * On return, val and length is set. The buffer returned in val must be freed + * by the caller. + */ +int kmip_parse_hex(const char *str, bool has_prefix, unsigned char **val, + uint32_t *length) +{ + unsigned char *buf; + BIGNUM *b = NULL; + int len, rc; + + if (str == NULL) + return -EINVAL; + + if (has_prefix && strncmp(str, "0x", 2) != 0) + return -EBADMSG; + + rc = BN_hex2bn(&b, str + (has_prefix ? 2 : 0)); + if (rc <= 0) + return -EBADMSG; + + len = BN_num_bytes(b); + buf = calloc(1, len); + if (buf == NULL) { + BN_free(b); + return -ENOMEM; + } + + if (BN_bn2bin(b, buf) != len) { + BN_free(b); + free(buf); + return -EIO; + } + + *val = buf; + *length = len; + + BN_free(b); + + return 0; +} + +/** + * Format a hex string from the byte array specified in val. The caller must + * free the returned str. + */ +int kmip_format_hex(const unsigned char *val, uint32_t length, bool prefix, + char **str) +{ + uint32_t str_len, i; + char tmp[4]; + char *ret; + + str_len = length * 2 + (prefix ? 2 : 0) + 1; + ret = calloc(1, str_len); + if (ret == NULL) + return -ENOMEM; + + if (prefix) + strcat(ret, "0x"); + + for (i = 0; i < length; i++) { + sprintf(tmp, "%02x", val[i]); + strcat(ret, tmp); + } + + *str = ret; + + return 0; +} + +/** + * Parse a hex string into a big number. + * On return, val and length is set. The buffer returned in val must be freed + * by the caller. + */ +int kmip_parse_bignum(const char *str, bool has_prefix, BIGNUM **bn) +{ + unsigned char *buf; + uint32_t len; + int rc; + + if (str == NULL) + return -EINVAL; + + rc = kmip_parse_hex(str, has_prefix, &buf, &len); + if (rc != 0) + return rc; + + rc = kmip_decode_bignum(buf, len, bn); + + free(buf); + + return rc; +} + +/** + * Format a hex string from a big number. The caller must free the returned str. + */ +int kmip_format_bignum(const BIGNUM *bn, bool prefix, char **str) +{ + unsigned char *buf; + uint32_t len; + int rc; + + len = kmip_encode_bignum_length(bn); + /* BIG INTEGERS must be a multiple of 8 bytes long */ + if ((len % KMIP_BIG_INTEGER_BLOCK_LENGTH) != 0) + len += KMIP_BIG_INTEGER_BLOCK_LENGTH - + (len % KMIP_BIG_INTEGER_BLOCK_LENGTH); + + buf = malloc(len); + if (buf == NULL) + return -ENOMEM; + + rc = kmip_encode_bignum(bn, buf, len); + if (rc != 0) { + free(buf); + return -EIO; + } + + rc = kmip_format_hex(buf, len, prefix, str); + + free(buf); + return rc; +} + +/** + * Decode a binary big integer in two's complement form into an OpenSSL BIGNUM. + */ +int kmip_decode_bignum(const unsigned char *data, uint32_t length, BIGNUM **bn) +{ + unsigned char *tmp = (unsigned char *)data; + int i, neg = 0, rc = 0; + + if (data == NULL || bn == NULL) + return -EINVAL; + + if (data[0] & 0x80) { + neg = 1; + + tmp = malloc(length); + if (tmp == NULL) + return -ENOMEM; + + for (i = 0; i < (int)length; i++) + tmp[i] = ~data[i]; + + for (i = length - 1; i >= 0; i--) { + tmp[i]++; + if (tmp[i] != 0x00) + break; + } + } + + *bn = BN_bin2bn(tmp, length, NULL); + if (*bn == NULL) { + rc = -EIO; + goto out; + } + BN_set_negative(*bn, neg); + +out: + if (neg) + free(tmp); + + return rc; +} + +/** + * Returns the length required by a binary big integer in two's complement form + */ +uint32_t kmip_encode_bignum_length(const BIGNUM *bn) +{ + uint32_t length; + + if (bn == NULL) + return 0; + + length = BN_num_bytes(bn); + if (BN_is_negative(bn) && BN_is_bit_set(bn, (length * 8) - 1)) + length += 1; + + return length; +} + +/** + * Encode an OpenSSL BIGNUM to a binary big integer in two's complement form, + * in the desired length. + */ +int kmip_encode_bignum(const BIGNUM *bn, unsigned char *data, uint32_t length) +{ + int i; + + if (bn == NULL || data == NULL) + return -EINVAL; + + if (BN_bn2binpad(bn, data, length) != (int)length) + return -EIO; + + if (BN_is_negative(bn)) { + for (i = 0; i < (int)length; i++) + data[i] = ~data[i]; + + for (i = length - 1; i >= 0; i--) { + data[i]++; + if (data[i] != 0x00) + break; + } + } + + return 0; +} + +/** + * Parse a timestamp in ISO8601 format and return it as time_t value + */ +int kmip_parse_timestamp(const char *str, int64_t *val) +{ + struct tm tm = { 0 }; + char *p; + int rc; + + rc = kmip_parse_hex_int(str, val); + if (rc == 0) + return 0; + if (rc != -EBADMSG) + return rc; + + p = strptime(str, KMIP_ISO8601_TIMESTAMP_TZ, &tm); + if (p == NULL) + p = strptime(str, KMIP_ISO8601_TIMESTAMP, &tm); + if (p == NULL || *p != 0) + return -EBADMSG; + + /* Adjust according to the parsed time zone */ + tm.tm_sec -= tm.tm_gmtoff; + tm.tm_gmtoff = 0; + tm.tm_isdst = 0; + + *val = (time_t)timegm(&tm); + + return 0; +} + +/** + * Parses a mask specification of the specified tag and separator character + */ +int kmip_parse_mask(enum kmip_tag tag, const char *str, char separator, + int64_t *val) +{ + const struct kmip_enum *info; + char *save_ptr, *s, *tok; + char delimiter[2]; + uint32_t enum_val; + int rc = 0; + + info = kmip_enum_info_by_tag(tag); + if (info == NULL) + return kmip_parse_hex_int(str, val); + + *val = 0; + + s = strdup(str); + if (s == NULL) + return -ENOMEM; + + delimiter[0] = separator; + delimiter[1] = 0; + tok = strtok_r(s, delimiter, &save_ptr); + while (tok != NULL) { + rc = kmip_enum_value_by_name_or_hex(info, tok, &enum_val); + if (rc != 0) + break; + + *val |= enum_val; + + tok = strtok_r(NULL, delimiter, &save_ptr); + } + + free(s); + return rc; +} + +static int kmip_append_string(char **str, int *str_len, char separator, + const char *append) +{ + int new_len; + char *tmp; + + if (str == NULL || str_len == NULL) + return -EINVAL; + + if (*str == NULL) + *str_len = 0; + + new_len = *str_len; + if (*str == NULL) + new_len++; + else if (separator != 0) + new_len++; + if (append != NULL) + new_len += strlen(append); + + tmp = realloc(*str, new_len); + if (tmp == NULL) + return -ENOMEM; + + if (*str == NULL) + memset(tmp, 0, new_len); + else if (separator != 0) + strncat(tmp, &separator, 1); + if (append != NULL) + strcat(tmp, append); + + *str = tmp; + *str_len = new_len; + + return 0; +} + +/** + * Format a mask specification of the specified tag and separator character + */ +int kmip_format_mask(enum kmip_tag tag, int32_t value, char separator, + char **str) +{ + const struct kmip_enum *info; + int rc = 0, i, s_len = 0; + char *s = NULL, *tmp; + + info = kmip_enum_info_by_tag(tag); + if (info == NULL || value == 0) + return kmip_format_hex((const unsigned char *)&value, + sizeof(value), true, str); + + /* Process all known mask bits */ + for (i = 0; value != 0 && info[i].name != NULL; i++) { + if (value & info[i].val) { + rc = kmip_append_string(&s, &s_len, separator, + info[i].name); + if (rc != 0) + goto out; + + value &= ~info[i].val; + } + } + + /* Any bits left in the value? */ + if (value != 0) { + rc = kmip_format_hex((const unsigned char *)&value, + sizeof(value), true, &tmp); + if (rc != 0) + goto out; + + rc = kmip_append_string(&s, &s_len, separator, tmp); + free(tmp); + if (rc != 0) + goto out; + + } + + *str = s; + +out: + if (rc != 0) + free(s); + + return rc; +} + +void kmip_print_dump(const char *func, unsigned char *data, size_t size, + unsigned int indent) +{ + char outstr[200], hexstr[4]; + size_t i; + + if (data == NULL) + return; + + strcpy(outstr, ""); + for (i = 0; i < size; i++) { + sprintf(hexstr, "%02x ", data[i]); + strcat(outstr, hexstr); + + if (i % 16 == 15) { + kmip_print_debug(func, "%*s%s", indent, "", + outstr); + strcpy(outstr, ""); + } + } + if (i % 16 != 0) + kmip_print_debug(func, "%*s%s", indent, "", outstr); +} + +static void kmip_print_bignum(const char *func, const BIGNUM *bn, + unsigned int indent) +{ + unsigned char *buf; + uint32_t len; + int rc; + + if (bn == NULL) + return; + + len = kmip_encode_bignum_length(bn); + buf = malloc(len); + if (buf == NULL) + return; + + rc = kmip_encode_bignum(bn, buf, len); + if (rc != 0) { + free(buf); + return; + } + + kmip_print_dump(func, buf, len, indent); + + free(buf); +} + +static void kmip_node_dump_int(struct kmip_node *node, unsigned int indent) +{ + enum kmip_tag tag, v1_attr_tag = 0; + struct kmip_node *element; + char outstr[200] = { 0 }; + struct tm *tm; + const char *s; + char *tmp; + time_t t; + int rc; + + if (node == NULL) + return; + + s = kmip_tag_name_by_tag(node->tag); + kmip_print_debug("kmip_node_dump", "%*sTag: %s (0x%x)", indent, "", + s ? s : "UNKNOWN", node->tag); + s = kmip_type_name_by_type(node->type); + kmip_print_debug("kmip_node_dump", "%*s Type: %s (0x%x)", indent, "", + s ? s : "UNKNOWN", node->type); + + if (node->name != NULL) + kmip_print_debug("kmip_node_dump", "%*s Name: %s", indent, + "", node->name); + + /* + * KMIP v1.x attribute values may be Enumerations or Integer Masks. + * To correctly print them, we need to know the tag. This is contained + * in a Attribute Name node, which is an element of our parent node. + */ + if (node->tag == KMIP_TAG_ATTRIBUTE_VALUE) + v1_attr_tag = kmip_find_v1_attribute_name_tag(node->parent); + tag = (v1_attr_tag != 0 ? v1_attr_tag : node->tag); + + switch (node->type) { + case KMIP_TYPE_STRUCTURE: + kmip_print_debug("kmip_node_dump", "%*s Elements (%u):", + indent, "", + kmip_node_get_structure_element_count(node)); + element = node->structure_value; + while (element != NULL) { + kmip_node_dump_int(element, indent + 4); + element = element->next; + } + break; + case KMIP_TYPE_INTEGER: + if (kmip_is_tag_mask(tag)) { + rc = kmip_format_mask(tag, node->integer_value, + '|', &tmp); + if (rc == 0) { + kmip_print_debug("kmip_node_dump", "%*s " + "Value: %s (0x%x)", + indent, "", tmp, + node->integer_value); + free(tmp); + break; + } + } + kmip_print_debug("kmip_node_dump", "%*s Value: %d (0x%x)", + indent, "", node->integer_value, + node->integer_value); + break; + case KMIP_TYPE_LONG_INTEGER: + kmip_print_debug("kmip_node_dump", "%*s Value: %ld (0x%lx)", + indent, "", node->long_value, + node->long_value); + break; + case KMIP_TYPE_BIG_INTEGER: + kmip_print_debug("kmip_node_dump", "%*s Value: (%u bytes)", + indent, "", kmip_encode_bignum_length( + node->big_integer_value)); + kmip_print_bignum("kmip_node_dump", node->big_integer_value, + indent + 4); + break; + case KMIP_TYPE_ENUMERATION: + s = kmip_enum_name_by_tag_value(tag, node->enumeration_value); + kmip_print_debug("kmip_node_dump", "%*s Value: %s (0x%x)", + indent, "", s ? s : "UNKNOWN", + node->enumeration_value); + break; + case KMIP_TYPE_BOOLEAN: + kmip_print_debug("kmip_node_dump", "%*s Value: %s", indent, "", + node->boolean_value ? "True" : "False"); + break; + case KMIP_TYPE_TEXT_STRING: + kmip_print_debug("kmip_node_dump", "%*s Value: '%s' " + "(%u characters)", indent, "", + node->text_value, strlen(node->text_value)); + break; + case KMIP_TYPE_BYTE_STRING: + kmip_print_debug("kmip_node_dump", "%*s Value: (%u bytes)", + indent, "", node->length); + kmip_print_dump("kmip_node_dump", node->bytes_value, + node->length, indent + 4); + break; + case KMIP_TYPE_DATE_TIME: + tm = gmtime((time_t *)&node->date_time_value); + if (tm != NULL) + strftime(outstr, sizeof(outstr), + KMIP_ISO8601_TIMESTAMP_UTC, tm); + else + strcpy(outstr, "INVALID"); + kmip_print_debug("kmip_node_dump", "%*s Value: %s (0x%lx)", + indent, "", outstr, node->date_time_value); + break; + case KMIP_TYPE_INTERVAL: + kmip_print_debug("kmip_node_dump", "%*s Value: %d (0x%x)", + indent, "", node->interval_value, + node->interval_value); + break; + case KMIP_TYPE_DATE_TIME_EXTENDED: + t = (time_t)node->date_time_ext_value / 1000000; + tm = gmtime(&t); + if (tm != NULL) + strftime(outstr, sizeof(outstr), + KMIP_ISO8601_TIMESTAMP_UTC, tm); + else + strcpy(outstr, "INVALID"); + kmip_print_debug("kmip_node_dump", "%*s Value: %s %lu (0x%lx)", + indent, "", outstr, + node->date_time_ext_value % 1000000, + node->date_time_ext_value); + break; + + default: + break; + } +} + + +/** + * Dump a KMIP node + * + * @param node the node to free + * @param debug if false, the function is a no-op + */ +void kmip_node_dump(struct kmip_node *node, bool debug) +{ + if (node == NULL || !debug) + return; + + kmip_node_dump_int(node, 0); +} + +/** + * Find a KMIP v1.x Attribute Name node in the elements of the specified parent + * node, and return the tag value of the attribute name. + * + * @param parent the parent node of the attribute name and value + * + * @returns the tag value of the attribute name, or 0 if not found, or unknown + * attribute name + */ +enum kmip_tag kmip_find_v1_attribute_name_tag(struct kmip_node *parent) +{ + struct kmip_node *e; + + if (parent == NULL) + return 0; + + if (parent->tag != KMIP_TAG_ATTRIBUTE) + return 0; + if (parent->type != KMIP_TYPE_STRUCTURE) + return 0; + + e = parent->structure_value; + while (e != NULL) { + /* + * A KMIP v2.x Vendor Attribute looks similar to a KMIP v1.x + * Attribute, but has a Vendor Identification node. If we find + * a Vendor Identification node, then it can't be a KMIP v1.x + * Attribute. + */ + if (e->tag == KMIP_TAG_VENDOR_IDENTIFICATION && + e->type == KMIP_TYPE_TEXT_STRING) + return 0; + + if (e->tag == KMIP_TAG_ATTRIBUTE_NAME && + e->type == KMIP_TYPE_TEXT_STRING) + return kmip_attr_tag_by_v1_attr_name(e->text_value); + + e = e->next; + } + + return 0; +} + diff --git a/libkmipclient/utils.h b/libkmipclient/utils.h new file mode 100644 index 00000000..89734feb --- /dev/null +++ b/libkmipclient/utils.h @@ -0,0 +1,61 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ +#ifndef UTILS_H +#define UTILS_H + +#include +#include + +#include + +#include "kmip.h" + +#define KMIP_BIG_INTEGER_BLOCK_LENGTH 8 + +#define KMIP_ISO8601_TIMESTAMP_UTC "%FT%TZ" +#define KMIP_ISO8601_TIMESTAMP_TZ "%FT%T%z" +#define KMIP_ISO8601_TIMESTAMP "%FT%T" + +#define kmip_debug(debug, fmt...) \ + do { \ + if (debug) \ + kmip_print_debug(__func__, fmt); \ + } while (0) + +void kmip_print_debug(const char *func, const char *fmt, ...); +void kmip_print_dump(const char *func, unsigned char *data, size_t size, + unsigned int indent); + +int kmip_parse_decimal_int(const char *str, int64_t *val); +int kmip_parse_decimal_uint(const char *str, uint64_t *val); + +int kmip_parse_hex_int(const char *str, int64_t *val); +int kmip_parse_hex(const char *str, bool has_prefix, unsigned char **val, + uint32_t *length); +int kmip_format_hex(const unsigned char *val, uint32_t length, bool prefix, + char **str); + +int kmip_parse_bignum(const char *str, bool has_prefix, BIGNUM **bn); +int kmip_format_bignum(const BIGNUM *bn, bool prefix, char **str); +int kmip_decode_bignum(const unsigned char *data, uint32_t length, BIGNUM **bn); +uint32_t kmip_encode_bignum_length(const BIGNUM *bn); +int kmip_encode_bignum(const BIGNUM *bn, unsigned char *data, uint32_t length); + +int kmip_parse_timestamp(const char *str, int64_t *val); + +int kmip_parse_mask(enum kmip_tag tag, const char *str, char separator, + int64_t *val); +int kmip_format_mask(enum kmip_tag tag, int32_t value, char separator, + char **str); + +void kmip_node_dump(struct kmip_node *node, bool debug); + +enum kmip_tag kmip_find_v1_attribute_name_tag(struct kmip_node *parent); + +#endif diff --git a/libkmipclient/xml.c b/libkmipclient/xml.c new file mode 100644 index 00000000..658bfdb1 --- /dev/null +++ b/libkmipclient/xml.c @@ -0,0 +1,490 @@ +/* + * libkmipclient - KMIP client library + * + * Copyright IBM Corp. 2021 + * + * s390-tools is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include +#include + +#include "kmip.h" +#include "names.h" +#include "utils.h" + +#define KMIP_XML_TTLV "TTLV" +#define KMIP_XML_TAG "tag" +#define KMIP_XML_NAME "name" +#define KMIP_XML_TYPE "type" +#define KMIP_XML_VALUE "value" + +/** + * Decode a KMIP node from the data in the XML node using the XML encoding. + * + * @param xml the XML node to decode + * @param parent the parent node or NULL if no parent exists. + * @param node On return: the decoded node.The newly allocated + * node has a reference count of 1. + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_decode_xml(const xmlNode *xml, struct kmip_node *parent, + struct kmip_node **node, bool debug) +{ + char *tag_attr = NULL, *name_attr = NULL, *type_attr = NULL; + enum kmip_tag tag, v1_attr_tag = 0; + char *tag_name, *value_attr = NULL; + struct kmip_node *n = NULL, *e; + uint64_t uint64; + xmlNode *child; + int64_t int64; + int rc = 0, i; + + if (xml == NULL || node == NULL) + return -EINVAL; + + if (xml->type != XML_ELEMENT_NODE) { + kmip_debug(debug, "Invalid XML node type: %d", xml->type); + return -EINVAL; + } + + n = calloc(1, sizeof(struct kmip_node)); + if (n == NULL) { + kmip_debug(debug, "calloc failed"); + return -ENOMEM; + } + n->ref_count = 1; + + if (strcmp((char *)xml->name, KMIP_XML_TTLV) == 0) { + tag_attr = (char *)xmlGetProp(xml, (xmlChar *)KMIP_XML_TAG); + if (tag_attr == NULL) { + kmip_debug(debug, "Missing '%s' attribute in XML node", + KMIP_XML_TAG); + rc = -EBADMSG; + goto out; + } + tag_name = tag_attr; + } else { + tag_name = (char *)xml->name; + } + n->tag = kmip_tag_by_name_or_hex(tag_name); + if (n->tag == 0) { + kmip_debug(debug, "Unknown 'tag' in XML object: '%s'", + tag_name); + rc = -EBADMSG; + goto out; + } + + name_attr = (char *)xmlGetProp(xml, (xmlChar *)KMIP_XML_NAME); + if (name_attr != NULL) + n->name = strdup(name_attr); + + type_attr = (char *)xmlGetProp(xml, (xmlChar *)KMIP_XML_TYPE); + if (type_attr == NULL) { + n->type = KMIP_TYPE_STRUCTURE; + } else { + n->type = kmip_type_by_name_or_hex(type_attr); + if (n->type == 0) { + kmip_debug(debug, "Unknown 'type' in JSON object: '%s'", + type_attr); + rc = -EBADMSG; + goto out; + } + } + + value_attr = (char *)xmlGetProp(xml, (xmlChar *)KMIP_XML_VALUE); + if (n->type != KMIP_TYPE_STRUCTURE && value_attr == NULL) { + kmip_debug(debug, "Missing '%s' attribute in XML node", + KMIP_XML_VALUE); + rc = -EBADMSG; + goto out; + } + + /* + * KMIP v1.x attribute values may be Enumerations or Integer Masks. + * To correctly decode them, we need to know the tag. This is contained + * in a Attribute Name node, which is an element of our parent node. + */ + if (n->tag == KMIP_TAG_ATTRIBUTE_VALUE) + v1_attr_tag = kmip_find_v1_attribute_name_tag(parent); + tag = (v1_attr_tag != 0 ? v1_attr_tag : n->tag); + + kmip_debug(debug, "tag: 0x%x type: 0x%x", n->tag, n->type); + + switch (n->type) { + case KMIP_TYPE_STRUCTURE: + for (child = xml->children, i = 0; child != NULL; + child = child->next, i++) { + if (child->type != XML_ELEMENT_NODE) + continue; + + rc = kmip_decode_xml(child, n, &e, debug); + if (rc != 0) { + kmip_debug(debug, "Failed to parse child " + "element %d", i); + goto out; + } + rc = kmip_node_add_structure_element(n, e); + kmip_node_free(e); + if (rc != 0) { + kmip_debug(debug, + "kmip_node_structure_add_element " + "failed: rc: %d", rc); + goto out; + } + } + break; + + case KMIP_TYPE_INTEGER: + case KMIP_TYPE_LONG_INTEGER: + case KMIP_TYPE_DATE_TIME_EXTENDED: + if (n->type == KMIP_TYPE_INTEGER && + kmip_is_tag_mask(tag)) { + rc = kmip_parse_mask(tag, value_attr, ' ', &int64); + if (rc != 0) { + kmip_debug(debug, "Failed to parse " + "mask string '%s'", value_attr); + goto out; + } + } else { + rc = kmip_parse_decimal_int(value_attr, &int64); + if (rc != 0) { + kmip_debug(debug, "Failed to parse " + "decimal string '%s'", value_attr); + goto out; + } + } + + switch (n->type) { + case KMIP_TYPE_INTEGER: + n->integer_value = int64; + break; + case KMIP_TYPE_LONG_INTEGER: + n->long_value = int64; + break; + case KMIP_TYPE_DATE_TIME_EXTENDED: + n->date_time_ext_value = int64; + break; + default: + break; + } + break; + + case KMIP_TYPE_INTERVAL: + rc = kmip_parse_decimal_uint(value_attr, &uint64); + if (rc != 0) { + kmip_debug(debug, "Failed to parse " + "decimal string '%s'", value_attr); + goto out; + } + n->interval_value = uint64; + break; + + case KMIP_TYPE_BIG_INTEGER: + rc = kmip_parse_bignum(value_attr, false, + &n->big_integer_value); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse bignum string '%s'", + value_attr); + goto out; + } + break; + + case KMIP_TYPE_ENUMERATION: + rc = kmip_enum_value_by_tag_name_or_hex(tag, value_attr, + &n->enumeration_value); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse enumeration '%s'", + value_attr); + goto out; + } + break; + + case KMIP_TYPE_BOOLEAN: + n->boolean_value = (strcmp(value_attr, "true") == 0 || + strcmp(value_attr, "1") == 0); + break; + + case KMIP_TYPE_TEXT_STRING: + n->text_value = strdup(value_attr); + if (n->text_value == NULL) { + rc = -ENOMEM; + goto out; + } + n->length = strlen(n->text_value); + break; + + case KMIP_TYPE_BYTE_STRING: + rc = kmip_parse_hex(value_attr, false, &n->bytes_value, + &n->length); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse hex string '%s'", + value_attr); + goto out; + } + break; + + case KMIP_TYPE_DATE_TIME: + rc = kmip_parse_timestamp(value_attr, &n->date_time_value); + if (rc != 0) { + kmip_debug(debug, + "Failed to parse time stamp '%s'", + value_attr); + goto out; + } + break; + + default: + kmip_debug(debug, "unknown type: 0x%x", n->type); + rc = -EBADMSG; + goto out; + } + + *node = n; + rc = 0; + +out: + if (rc != 0 && n != NULL) + kmip_node_free(n); + if (tag_attr != NULL) + xmlFree(tag_attr); + if (name_attr != NULL) + xmlFree(name_attr); + if (type_attr != NULL) + xmlFree(type_attr); + if (value_attr != NULL) + xmlFree(value_attr); + + return rc; +} + +/** + * Encode a KMIP node into an XML node using the XML encoding. + * + * @param node the node to encode + * @param xml On return: the XML node + * @param debug if true, debug messages are printed + * + * @returns 0 in case of success, or a negative errno value + */ +int kmip_encode_xml(const struct kmip_node *node, xmlNode **xml, bool debug) +{ + enum kmip_tag tag, v1_attr_tag = 0; + xmlNode *ret_xml = NULL, *elem_xml; + struct kmip_node *element; + const char *tag_name; + char tmp_str[50]; + const char *str; + struct tm *tm; + xmlAttr *attr; + char *tmp; + int rc; + + if (node == NULL || xml == NULL) + return -EINVAL; + + kmip_debug(debug, "tag: 0x%x type: 0x%x", node->tag, node->type); + + tag_name = kmip_tag_name_by_tag(node->tag); + if (tag_name != NULL) + ret_xml = xmlNewNode(NULL, (xmlChar *)tag_name); + else + ret_xml = xmlNewNode(NULL, (xmlChar *)KMIP_XML_TTLV); + if (ret_xml == NULL) { + kmip_debug(debug, "Failed to allocate a XML node"); + return -ENOMEM; + } + + if (tag_name == NULL) { + sprintf(tmp_str, "0x%06x", node->tag); + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_TAG, + (xmlChar *)tmp_str); + if (attr == NULL) { + kmip_debug(debug, + "Failed to add '%s' attribute to XML node", + KMIP_XML_TAG); + rc = -ENOMEM; + goto out; + } + + if (node->name != NULL) { + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_NAME, + (xmlChar *)node->name); + if (attr == NULL) { + kmip_debug(debug, "Failed to add '%s' " + "attribute to XML node", + KMIP_XML_NAME); + rc = -ENOMEM; + goto out; + } + } + } + + if (node->type != KMIP_TYPE_STRUCTURE) { + str = kmip_type_name_by_type(node->type); + if (str == NULL) { + kmip_debug(debug, "unknown type 0x%x", node->type); + rc = -EINVAL; + goto out; + } + + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_TYPE, + (xmlChar *)str); + if (attr == NULL) { + kmip_debug(debug, + "Failed to add '%s' attribute to XML node", + KMIP_XML_TYPE); + rc = -ENOMEM; + goto out; + } + } + + /* + * KMIP v1.x attribute values may be Enumerations or Integer Masks. + * To correctly encode them, we need to know the tag. This is contained + * in a Attribute Name node, which is an element of our parent node. + */ + if (node->tag == KMIP_TAG_ATTRIBUTE_VALUE) + v1_attr_tag = kmip_find_v1_attribute_name_tag(node->parent); + tag = (v1_attr_tag != 0 ? v1_attr_tag : node->tag); + + switch (node->type) { + case KMIP_TYPE_STRUCTURE: + element = node->structure_value; + while (element != NULL) { + rc = kmip_encode_xml(element, &elem_xml, debug); + if (rc != 0) { + kmip_debug(debug, "kmip_encode_json failed"); + goto out; + } + if (xmlAddChild(ret_xml, elem_xml) == NULL) { + kmip_debug(debug, "xmlAddChild failed"); + rc = -EIO; + goto out; + } + element = element->next; + } + attr = NULL; + break; + + case KMIP_TYPE_INTEGER: + if (kmip_is_tag_mask(tag) && node->integer_value != 0) { + rc = kmip_format_mask(tag, node->integer_value, + ' ', &tmp); + if (rc != 0) { + kmip_debug(debug, "kmip_format_mask failed"); + goto out; + } + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp); + free(tmp); + } else { + sprintf(tmp_str, "%d", node->integer_value); + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp_str); + } + break; + + case KMIP_TYPE_INTERVAL: + sprintf(tmp_str, "%u", node->interval_value); + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp_str); + break; + + case KMIP_TYPE_LONG_INTEGER: + sprintf(tmp_str, "%ld", node->long_value); + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp_str); + break; + + case KMIP_TYPE_BIG_INTEGER: + rc = kmip_format_bignum(node->big_integer_value, false, &tmp); + if (rc != 0) { + kmip_debug(debug, "kmip_format_bignum failed"); + goto out; + } + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp); + free(tmp); + break; + + case KMIP_TYPE_ENUMERATION: + str = kmip_enum_name_by_tag_value(tag, node->enumeration_value); + if (str != NULL) { + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)str); + } else { + sprintf(tmp_str, "0x%08x", node->enumeration_value); + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp_str); + } + break; + + case KMIP_TYPE_BOOLEAN: + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)(node->boolean_value ? + "true" : "false")); + break; + + case KMIP_TYPE_TEXT_STRING: + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)node->text_value); + break; + + case KMIP_TYPE_BYTE_STRING: + rc = kmip_format_hex(node->bytes_value, node->length, + false, &tmp); + if (rc != 0) { + kmip_debug(debug, "kmip_format_hex_long failed"); + goto out; + } + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp); + free(tmp); + break; + + case KMIP_TYPE_DATE_TIME: + tm = gmtime((time_t *)&node->date_time_value); + strftime(tmp_str, sizeof(tmp_str), KMIP_ISO8601_TIMESTAMP_UTC, + tm); + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp_str); + break; + + case KMIP_TYPE_DATE_TIME_EXTENDED: + sprintf(tmp_str, "%ld", node->date_time_ext_value); + attr = xmlSetProp(ret_xml, (xmlChar *)KMIP_XML_VALUE, + (xmlChar *)tmp_str); + break; + + default: + kmip_debug(debug, "unknown type: 0x%x", node->type); + rc = -EINVAL; + goto out; + } + + if (attr == NULL && node->type != KMIP_TYPE_STRUCTURE) { + kmip_debug(debug, "Failed to add '%s' " + "attribute to XML node", + KMIP_XML_VALUE); + rc = -ENOMEM; + goto out; + } + + rc = 0; + *xml = ret_xml; + +out: + if (rc != 0) + xmlFreeNode(ret_xml); + + return rc; +} +