The KMIP Server Library (KSL) product extends our powerful KMIP client parsing library (i.e., SKC) to be able to parse server side requests. This product includes a server side parser and all the functions needed to send a properly encoded response back to a KMIP client. The idea is that a vendor, who has a key server, can now use KSL to add a KMIP protocol front end. The server vendor will still have to implement all server side mechanisms, but will not have to deal with the complexity of parsing or generating TTLV, XML, and JSON KMIP messages.
KSL is available on Windows and Linux. It supports a C++, C, and Java Native Interface (JNI) language bindings. KSL supports all KMIP operations that are defined for KMIP 1.0, 1.1, 1.2, 1.3, and 1.4 except for: Validate, Import and Export. Support for KMIP 1.4 operations Import and Export will be added in the near future. KMIP 2.0 support will also be added at a future date once the specification for that protocol version is published.
A description of the unique design of P6R KMIP products can be found at: https://www.p6r.com/articles/2012/01/30/p6r-kmip-toolkit-introduction/
The C/C++ API allows the developer to set the following configurations directly. However, the JNI API requires that these values are set in the p6kmipserverlib.conf file.
The "parseMaxBufSize" configuration parameter (postive numeric value), defines the buffer size allocated (in bytes) to place incoming KMIP requests into so they can be parsed. The default value is 70,000 bytes.
The "parseInitialBufCount" configuration parameter (positive numeric value), defines the number of memory buffers (used to parse incoming KMIP requests) to be initially allocated. The default value is 3.
The "parseGrowBufBy" configuration parameter (positive numeric value), defines the number of memory buffers (used to parse incomin KMIP requests) to be allocated at a time. The default value is 3.
The "responseMaxBufSize" configuration parameter (postive numeric value), defines the buffer size allocated (in bytes) to place generated KMIP response messages into. The default value is 70,000 bytes.
The "responseInitialBufCount" configuration parameter (positive numeric value), defines the number of memory buffers (used to generate KMIP responses) to be initially allocated. The default value is 3.
The "responseGrowBufBy" configuration parameter (positive numeric value), defines the number of memory buffers (used to generate KMIP responses) to be allocated at a time. The default value is 3.
The KMIP protocol often returns a list of items back from an operation (e.g., attributes of a key). The size of this list can be unknown by the server application. To deal with this our API uses enumerators (in Java these are called iterators). Enumerators are heavily relied upon in our API and so once you are familiar with using one they are practically all the same (of course each enumerator returns different data / structures).
Here is a list of the current enumerator classes: P6R::p6IKMIPVersions – returns the protocol versions supported by a KMIP sever P6R::p6IKMIPEnum – returns KMIP enumeration values (e.g., the different KMIP operations that a server supports via the Query operation) P6R::p6IKMIPStr – returns strings such as unique identifiers to managed objects such as keys, certificates P6R::p6IKMIPBinary – returns binary blobs P6R::p6IKMIPAttribute – returns a list of attributes associated with a managed object like a key or certificate (note that there are many types of attributes) P6R::p6IKMIPNamespace – returns a list of application namespaces P6R::p6IKMIPName – returns a list of KMIP template names P6R::p6IKMIPExtInfo – returns a list of KMIP extension information values P6R::p6IKMIPResult – use in API functions that perform multiple operations at the same time (e.g., addAttributes()) P6R::p6IKMIPValInfo – returns a list of server or client validations (e.g., FIPS, common critera) and is new in KMIP 1.3 P6R::p6IKMIPProfileInfo – returns a list of server or client conformance profiles and is new in KMIP 1.3 P6R::p6IKMIPRNGInfo – returns a list of random number generators supported by a KMIP server and is new in KMIP 1.3 P6R::p6IKMIPBatchItems – returns one or more batch items that comprise an incoming request message from a KMIP client
When enumerators return a text string or byte array the call of the enumerator must provide a buffer to which a value stored in the enumerator is copied. For example, looking at the p6IKMIPAttribute enumerator (see p6kmipbase.h) returns structures of the type P6KMIP_OBJECT_ATTRIBUTE, which allows many different attributes to be returned to the caller. Lets pick one such attribute for this example, "P6NCSTR contactInformation". The type P6NCSTR contains a pointer to a string and its corresponding length. When calling the p6IKMIPAttribute enumerator to extract the contact information attribute value the field contactInformation.pString needs to point to an allocated buffer that is being passed into the enumerator. To be clear the enumerator does not return back a pointer to a buffer the calling code must pass in a buffer so the contact information can be copied into it. Now how does the calling code know how big a buffer to allocate? Just set the contactInformation.pString field to NULL and upon return from the call the contactInformation.length field will return the required buffer size (and typically the function will return the error code eTooSmall). The whole purpose of this approach is to reduce memory leaks by following the simple rule that the code which allocated a memory block is responsible for freeing it. The all code allocated internally by an enumerator is freed by that enumerator and is not passed out to a caller.
The vendor using KSL implements all of the server's network software receiving messages over a network connection from a KMIP client. These messages (in TTLV, XML, or JSON) are stored in a buffer and it is that buffer that is passed into the KSL parser. To do this the server creates an instance of the P6R::p6IKMIPServerParser component (see file p6kmipserverparser.h) and calls the function:
The "msgFormat" parameter indicates whether the data in pInBuffer is in TTLV, XML, or JSON (which can be determined from how the KMIP client sends the message). This function parses the incoming KMIP client request and returns an error if the message is improperly constructed.
Next the server calls the following function to receive an instance of the P6R::p6IKMIPBatchItems enumerator that contains all the batched items in the incoming KMIP request.
This function also returns a KMIP message's request header information via the first parameter (which includes, for example, the KMIP protocol version being used). At this point KSL's job is mostly done and the server application needs to process each batch item in the request (e.g., Create a new key).
After the server application has processed each batch item in the client request it can then use the KSL library to generate the properly formated KMIP response message by using the P6R::p6IKMIPServerResponse component (see file p6kmipserverresponse.h). The server application calls the function:
The server's response is formated as an array of P6KMIP_OUTGOING_RESPONSE structures (one entry to match each batch item in the request) and this function places the properly formated KMIP response message into the pResponse buffer. Next the server application handles sending the generated KMIP response message back over the network to the KMIP client.
In summary, KSL translates an incoming KMIP request into a parsed set of batch items that a server application can process and then transaltes an array of batch responses back into KMIP to return to the client. All network and KMIP batch request processing are implemented by the server vendor and all KMIP interface processing is handled by KSL.
The P6R::p6IKMIPServerParser and P6R::p6IKMIPServerResponse components are not multi-thread safe. There are several practical ways for a server application to ensure that proper access to these components are controlled in multi-threaded applications. Any number of these components can be created and freed so for example one set of instances could be created per thread that was handling a single KMIP client request.
P6R's KMIP server library follows the standards defined in the following documents.
1) KMIP Test Cases Version 1.4, http://docs.oasis-open.org/kmip/testcases/v1.4/cn01/kmip-testcases-v1.4-cn01.html
2) KMIP Test Cases Version 1.3, http://docs.oasis-open.org/kmip/testcases/v1.3/kmip-testcases-v1.3.html
3) KMIP Test Cases Version 1.2, http://docs.oasis-open.org/kmip/testcases/v1.2/kmip-testcases-v1.2.html
4) KMIP Test Cases Version 1.1, http://docs.oasis-open.org/kmip/testcases/v1.1/kmip-testcases-v1.1.html
5) OASIS, "Key Management Interoperability Protocol Specification 1.0", OASIS Standard, 01 October 2010, http://docs.oasis-open.org/kmip/spec/v1.0/os/kmip-spec-1.0-os.html
6) OASIS, "Key Management Interoperability Protocol Specification 1.1", OASIS Standard, 24 January 2013, http://docs.oasis-open.org/kmip/spec/v1.1/os/kmip-spec-v1.1-os.pdf
7) OASIS, "Key Management Interoperability Protocol Specification 1.2", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/spec/v1.2/os/kmip-spec-v1.2-os.html
8) OASIS, "Key Management Interoperability Protocol Specification 1.3", OASIS Standard, 27 December 2016, http://docs.oasis-open.org/kmip/spec/v1.3/os/kmip-spec-v1.3-os.pdf
9) OASIS, "Key Management Interoperability Protocol Specification 1.4", OASIS Standard, 22 November 2017, http://docs.oasis-open.org/kmip/spec/v1.4/os/kmip-spec-v1.4-os.html
10) OASIS, "Key Management Interoperability Protocol Specification 2.0", Working Draft 01, 06 December 2017,
11) OASIS, "KMIP Additional Message Encodings Version 1.0", OASIS Standard, 19 May 2015 2015, http://docs.oasis-open.org/kmip/kmip-addtl-msg-enc/v1.0/os/kmip-addtl-msg-enc-v1.0-os.html
12) OASIS, "KMIP Asymmetric Key Lifecycle Profile Version 1.0", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/kmip-asym-key-profile/v1.0/os/kmip-asym-key-profile-v1.0-os.html
13) OASIS, "KMIP Cryptographic Services Profile Version 1.0", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/kmip-cs-profile/v1.0/os/kmip-cs-profile-v1.0-os.html
14) OASIS, "KMIP Symmetric Key Foundry for FIPS 140-2 Profile Version 1.0", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/kmip-sym-foundry-profile/v1.0/os/kmip-sym-foundry-profile-v1.0-os.html
15) OASIS, "KMIP Symmetric Key Lifecycle Profile Version 1.0", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/kmip-sym-key-profile/v1.0/os/kmip-sym-key-profile-v1.0-os.pdf
16) OASIS, "KMIP Opaque Managed Object Store Profile Version 1.0", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/kmip-opaque-obj-profile/v1.0/os/kmip-opaque-obj-profile-v1.0-os.html
17) OASIS, "KMIP Tape Library Profile Version 1.0", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/kmip-tape-lib-profile/v1.0/os/kmip-tape-lib-profile-v1.0-os.html
18) OASIS, "KMIP Storage Array with Self-Encrypting Drives Profile Version 1.0", OASIS Standard, 19 May 2015, http://docs.oasis-open.org/kmip/kmip-sa-sed-profile/v1.0/os/kmip-sa-sed-profile-v1.0-os.pdf
19) OASIS, "KMIP Suite B Profile Version 1.0", OASIS Standard, 19 May 2015. http://docs.oasis-open.org/kmip/kmip-suite-b-profile/v1.0/os/kmip-suite-b-profile-v1.0-os.html
This JNI implementation exposes a large subset of P6R's KMIP Server Library (KSL) SDK which is implemented in C++. The underlying SKC KMIP implementation is full featured supporting KMIP protocol versions: 1.0, 1.1, 1.2, 1.3, and 1.4. If there is something missing from the JNI KMIP API that you need please let us know and we will be happy to add it.
This KMIP JNI implementation is easy to use and follows standard Java practices (e.g., using Exceptions instead of return error codes). We have tested this JNI implementation with a set of JUNIT tests that we have included for your use and as examples of how to use this KMIP API. We got so used to this Java API we forgot that the underlying KMIP implementation was actually in C++.
Please refer to the included javadoc for each of these classes.
First the normal KSL library setup is required. All P6R KMIP code runs out of one, writable, directory. Once that is created copy the file libp6javakmipserverlib.so (for linux) and p6javakmipserverlib.dll into this one "run" directory. This file is the JNI bridge between the p6kmipserverlib.jar Java file and the KSL library. As defined in the Java Classpath section below the full path of this run directory must also appear in the Java Classpath so that Java can find this file. Meanwhile the p6kmipserverlib.jar file can be placed with the rest of your java application in any directory you choose.
For the Java code in the p6kmipserverlib.jar file to find and load the JNI implementation the single P6R "run" directory must be specified on the command line with "-Djava.library.path=<full path to run directory>" (see below). This is set by the calling Java application and not by the JNI implementation.
All the JUNIT test cases can be run on Linux (we tested on Centos 6) via the command line as follows:
2) KSL library is running out of the /home/mjoseph/ksl-2017.1.2101/Linux2.6_x86_OPT_64bit_gcc.OBJ directory.
3) The /home/mjoseph/temp/2017.1.2101/artifacts/64/Linux/Release/libp6javakmipserverlib.so has been copied into the /home/mjoseph/ksl-2017.1.2101/Linux2.6_x86_OPT_64bit_gcc.OBJ directory
4) If ran in the /home/mjoseph/temp/2017.1.2101/javakmipserver directory
java -ea -Djava.library.path=/home/mjoseph/ksl-2017.1.2101/Linux2.6_x86_OPT_64bit_gcc.OBJ -cp .:/home/mjoseph/temp/2017.1.2101/javakmipserver/lib/hamcrest-all-1.3.jar: /home/mjoseph/temp/2017.1.2101/javakmipserver/lib/hamcrest-core-1.3.jar:/home/mjoseph/temp/2017.1.2101/javakmipserver/lib/junit-4.12.jar: /home/mjoseph/temp/2017.1.2101/javakmipserver/p6kmipserverlib.jar org.junit.runner.JUnitCore com.p6r.kmipserverlib.JniBasicKmip
Notice the following about this command: (1) the current directory is in the classpath ".:/", (2) the "/home/mjoseph/temp/2017.1.2101" needs to be replaced with the full path of where the javakmipserverlib directory is installed (e.g., /home/youraccount), and (3) "com.p6r.kmipserverlib.JniBasicKmip" is the name of one of the JUNIT class files in the ../2017.1.2101/artifacts/test/com/p6r/kmipserverlib/ directory.
Here what the output when running the JniBasicKmip unit test:
1) Rob Gordon, "Essential JNI: Java Native Interface", Prentice Hall PTR, 1998, ISBN 0-13-679895-0.
2) Java Programming Tutorial, Java Native Interface (JNI), http://www.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html.
3) S.Stricker, Java programming with JNI, http://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni.html.