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; +} +