Developer's Guide
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ex-kmip-1.cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory> // nothrow
#include "p6skc.h"
#include "p6config.h"
#include "p6file.h"
#include "p6dir.h"
#include "p6gencerts.h"
#include "p6genkeys.h"
#include "cconsolestream.h"
using namespace P6R;
P6DECLARE_CID( p6KMIPClient );
P6DECLARE_CID( p6WConfig );
P6DECLARE_CID( p6Time );
P6DECLARE_CID( p6IoBufferFactory );
P6DECLARE_CID( p6EntropySource );
P6DECLARE_CID( p6Random );
P6DECLARE_IID( p6IRunningIface );
P6DECLARE_CID( p6Cert );
P6DECLARE_CID( p6GenCerts );
P6DECLARE_CID( p6GenKeys );
P6DECLARE_CID( p6Sign );
P6DECLARE_CID( p6SymmetricCrypto );
P6DECLARE_CID( p6EncryptEnvelope );
P6DECLARE_CID( p6DecryptEnvelope );
P6DECLARE_CID( p6CryptoKey );
P6DECLARE_CID( p6Dir );
P6DECLARE_CID( p6UnbufferedFile );
P6DECLARE_CID( p6Keystore );
namespace {
class CKmipExample1
{
public:
P6CLASSMETHOD initialize();
P6CLASSMETHOD run( p6IDataStream *pStreamDebug );
CKmipExample1()
: m_port(0), m_compatMask(0), m_pHostName(NULL)
{
}
~CKmipExample1()
{
if (NULL != m_pHostName) m_cpStr->wstrfree( m_pHostName );
if (NULL != m_cpStoreInit) m_cpStoreInit->close();
}
protected:
P6CLASSMETHOD setPreferences( P6KMIP_PREF* pPrefs, P6WCHAR* pLogDir, P6UINT16 asynchronous, P6UINT32 privateKeyEncoding, P6UINT32 publicKeyEncoding,
P6UINT32 symmetricKeyEncoding, P6UINT32 maxBufferSize, P6UINT32 connectTimeout, P6UINT32 sendTimeout, P6UINT32 receiveTimeout,
P6UINT32 initialBufCount, P6UINT32 growBufsBy );
P6CLASSMETHOD extractUniqueId( p6IKMIPStr* pEnum, P6NCSTR* pUniqueId );
P6CLASSMETHOD createSession( p6IKMIPClient* pClient, P6BOOL bWithCredentials );
P6CLASSMETHOD getRNG(P6R::p6IRandom **ppRandom);
P6CLASSMETHOD getIGenKeys( p6IGenKeys** ppGenKeys );
P6CLASSMETHOD savePrivKeyInStore( p6IKeystore* pKeystore, const P6WCHAR* pNamespace, const P6WCHAR* pName, const P6WCHAR* pFilePath, P6UINT32 keySize );
P6CLASSMETHOD saveClientCertInStore( p6IKeystore* pKeystore, const P6WCHAR* pNamespace, const P6WCHAR* pName, const P6WCHAR* pFilePath );
P6CLASSMETHOD saveRootCertInStore( p6IKeystore* pKeystore, const P6WCHAR* pNamespace, const P6WCHAR* pFilePath );
P6CLASSMETHOD createKeystore( const P6WCHAR* pKeystoreName, const P6WCHAR* rootPEM, const P6WCHAR* certPEM, const P6WCHAR* privPEM, P6UINT32 privSize, p6IKeystoreInit** pInit, p6IKeystore** pKeystore );
P6CLASSMETHOD loadKeyFromFile( const P6WCHAR* pwszFilename, P6UINT32 keySize, p6ICryptoKey** ppNewKey );
P6CLASSMETHOD loadCertificateFromFile( const P6WCHAR* pPath, p6ICert** ppNewCert );
P6CLASSMETHOD createPKCS8Key( P6BSTR keyBuffer, P6SIZE keySize, p6ICryptoKey** ppNewKey );
protected:
p6ComPtr<p6ISymmetricCrypto> m_cpCrypto; // -> used to encrypt the contents of the keystore
p6ComPtr<p6ICryptoKey> m_cpSignKey; // ->
p6ComPtr<p6IRandom> m_cpRandom;
p6ComPtr<p6IKeystore> m_cpKeystore; // -> the KMIP client requires that a properly initialzed keystore is setup
P6UINT32 m_port;
P6UINT32 m_compatMask; // -> compatibility mask: 0 use TTLV message encoding, 2 use XML message encoding, 4 use JSON message encoding
P6WCHAR* m_pHostName;
};
// create the key file (supplied by the server vendor) into a key object for SSL
P6CLASSMETHODIMPL CKmipExample1::createPKCS8Key( P6BSTR keyBuffer, P6SIZE keySize, p6ICryptoKey** ppNewKey )
{
P6ERR err = eOk;
if (P6SUCCEEDED( err = p6CreateCryptoInstance( CID_p6CryptoKey, VALIDATECOMPTR( p6ICryptoKeyInit, cpKeyInit ))))
{
if (P6SUCCEEDED( err = cpKeyInit->initialize( P6CKF_NONE, m_cpRandom )))
{
if (P6SUCCEEDED( err = cpKeyInit->loadPKCS8Key( keyBuffer.pString, (P6UINT32) keyBuffer.length, (P6UINT32) keySize )))
{
err = cpKeyInit->queryInterface( VALIDATEIF( p6ICryptoKey, ppNewKey ));
}
}
}
return err;
}
// load the KMIP server vendor supplied certificate file for SSL
P6CLASSMETHODIMPL CKmipExample1::loadCertificateFromFile( const P6WCHAR* pPath, p6ICert** ppNewCert )
{
P6ERR err = eOk;
if (P6FAILED( err = p6CreateCryptoInstance( CID_p6Cert, VALIDATECOMPTR( p6ICertInit, cpInit )))) return err;
if (P6FAILED( err = cpInit->initialize( P6CERT_NOFLAGS )))
{
return err;
}
if (P6SUCCEEDED( err = cpInit->loadCert( pPath ))) {
err = cpInit->queryInterface( VALIDATEIF( p6ICert, ppNewCert ));
}
return err;
}
// load the PEM private key file (supplied by the server vendor) for SSL
P6CLASSMETHODIMPL CKmipExample1::loadKeyFromFile( const P6WCHAR* pwszFilename, P6UINT32 keySize, p6ICryptoKey** ppNewKey )
{
P6BSTR keyBuffer = {NULL, 0};
P6UINT32 cBytesRead = 0;
P6ERR err = eNotFound;
if (NULL == pwszFilename) return eInvalidArg;
if (P6SUCCEEDED( err = p6CreateInstance( NULL, CID_p6UnbufferedFile, VALIDATECOMPTR( p6IUnbufferedFile, cpFile ))))
{
if (P6SUCCEEDED( err = cpFile->initialize()))
{
if (P6SUCCEEDED( err = cpFile->open( pwszFilename, P6FILE_READ|P6FILE_OPENEXISTING,P6FP_DEFAULT )))
{
P6FILEINFO info;
if ( P6SUCCEEDED( err = cpFile->stat( &info )))
{
if (info.m_cSize)
{
P6CHAR* pBuffer = new (std::nothrow) P6CHAR[(P6UINT32)info.m_cSize];
if ( pBuffer )
{
if (P6SUCCEEDED( err = cpFile->read( pBuffer,(P6UINT32)info.m_cSize, &cBytesRead )))
{
if (cBytesRead == info.m_cSize)
{
keyBuffer.length = cBytesRead;
keyBuffer.pString = (P6UCHAR*)pBuffer;
err = createPKCS8Key( keyBuffer, keySize, ppNewKey ); // or PKCS1?
}
}
}
else err = eIoError;
delete [] pBuffer;
}
else err = eNoMemory;
}
else {
err = eTooSmall;
}
cpFile->close();
}
}
}
return err;
}
// The contents of the keystore is protected by a key
P6CLASSMETHODIMPL CKmipExample1::getIGenKeys( p6IGenKeys** ppGenKeys )
{
P6ERR err = eOk;
*ppGenKeys = NULL;
//
// Create an instance of the p6IGenKeys interface
// and then initilize it for use.
//
if (P6SUCCEEDED(err = p6CreateCryptoInstance( CID_p6GenKeys, VALIDATECOMPTR( p6IGenKeys, cpGenKeys ))))
{
if(P6SUCCEEDED(err = cpGenKeys->initialize( P6GENKEY_NOFLAGS, m_cpRandom )))
{
//
// On success, return an addref'd pointer to the
// interface, following P6COM reference counting rules.
// The detach method, transfers ownership of the interface
// to ppGenKeys without unneeded reference counting operations.
//
cpGenKeys.detach(ppGenKeys);
}
}
return err;
}
// Load in the certs we need to connect to the KMIP server into our new store
P6CLASSMETHODIMPL CKmipExample1::saveRootCertInStore( p6IKeystore* pKeystore, const P6WCHAR* pNamespace, const P6WCHAR* pFilePath )
{
P6WCHAR confPath[P6MAXPATH+2]= {0};
P6WCHAR szHash[20] = {0};
P6SIZE nHash = 0;
P6ERR err = eOk;
p6ComPtr<p6ICert> cpNewCert;
P6ARG args[2];
if (P6FAILED( err = p6GetDirectory( P6D_CONF, confPath, P6MAXPATH, NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( confPath, P6CNTOF(confPath), P6TEXT("/"), NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( confPath, P6CNTOF(confPath), pFilePath, NULL ))) return err;
if ( P6SUCCEEDED( err = loadCertificateFromFile( confPath, cpNewCert.addressof() )))
{
// SSL library expects a specific namespace depending on how the cert is used
if (P6SUCCEEDED( err = cpNewCert->getSubjectHash( &nHash )))
{
P6AI_SIZE_HEXL( args, nHash );
if (P6SUCCEEDED( err = m_cpStr->formatStringW( szHash, P6CNTOF(szHash), NULL, P6TEXT("%1$"), args, 1 )))
err = pKeystore->setCertificate( pNamespace, szHash, cpNewCert, NULL );
}
}
return err;
}
P6CLASSMETHODIMPL CKmipExample1::saveClientCertInStore( p6IKeystore* pKeystore, const P6WCHAR* pNamespace, const P6WCHAR* pName, const P6WCHAR* pFilePath )
{
P6ERR err = eOk;
P6WCHAR confPath[P6MAXPATH+2] = {0};
p6ComPtr<p6ICert> cpNewCert;
if (P6FAILED( err = p6GetDirectory( P6D_CONF, confPath, P6MAXPATH, NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( confPath, P6CNTOF(confPath), P6TEXT("/"), NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( confPath, P6CNTOF(confPath), pFilePath, NULL ))) return err;
if ( P6SUCCEEDED( err = loadCertificateFromFile( confPath, cpNewCert.addressof() )))
{
err = pKeystore->setCertificate( pNamespace, pName, cpNewCert, NULL );
}
return err;
}
// Load in the keys we need to connect to the KMIP server into our new store
P6CLASSMETHODIMPL CKmipExample1::savePrivKeyInStore( p6IKeystore* pKeystore, const P6WCHAR* pNamespace, const P6WCHAR* pName, const P6WCHAR* pFilePath, P6UINT32 keySize )
{
P6ERR err = eOk;
P6WCHAR confPath[P6MAXPATH+2] = {0};
if (P6FAILED( err = p6GetDirectory( P6D_CONF, confPath, P6MAXPATH, NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( confPath, P6CNTOF(confPath), P6TEXT("/"), NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( confPath, P6CNTOF(confPath), pFilePath, NULL ))) return err;
if ( P6SUCCEEDED( err = loadKeyFromFile( confPath, keySize, cpNewKey.addressof() )))
{
err = pKeystore->setKey( pNamespace, pName, cpNewKey, NULL, 0, NULL );
}
return err;
}
// Create a keystore and then load it with the information we need to connect to the KMIP server.
// P6R's SSL looks into the keystore for certificates and the private key when it starts a connection to the KMIP server.
P6CLASSMETHODIMPL CKmipExample1::createKeystore( const P6WCHAR* pKeystoreName, const P6WCHAR* rootPEM, const P6WCHAR* certPEM, const P6WCHAR* privPEM, P6UINT32 privSize, p6IKeystoreInit** ppInit, p6IKeystore** ppKeystore )
{
P6ERR err = eOk;
*ppInit = NULL;
*ppKeystore = NULL;
// Create the keystore and fill it with vendor provided SSL certificates
if (P6FAILED( err = p6CreateInstance( NULL, CID_p6Keystore, VALIDATEIF( p6IKeystoreInit, ppInit )))) return err;
err = (*ppInit)->queryInterface( VALIDATEIF( p6IKeystore, ppKeystore ));
if (P6FAILED( err = (*ppInit)->initialize( P6KEYSTORE_NOFLAGS, m_cpCrypto, SH_SHA256, m_cpSignKey )))
{
if (NULL != (*ppKeystore)) (*ppKeystore)->release();
(*ppKeystore) = NULL;
(*ppInit)->release();
(*ppInit) = NULL;
return err;
}
/*
* The first parameter of openSigned() is the file path where to create and access keystore databases.
* If NULL, then the keystore location will default to the P6R database directory.
* If the SKC is installed in a read-only directory then the first parameter will need to be set to
* an existing read/write directory.
*/
if (P6FAILED( err = (*ppInit)->openSigned( NULL, pKeystoreName )))
{
if (NULL != (*ppKeystore)) (*ppKeystore)->release();
(*ppKeystore) = NULL;
(*ppInit)->release();
(*ppInit) = NULL;
return err;
}
if (P6FAILED( err = saveRootCertInStore( (*ppKeystore), P6TEXT("p6r.trustedroot"), rootPEM ))) return err;
if (P6FAILED( err = saveClientCertInStore( (*ppKeystore), P6TEXT("p6r.clientauth"), m_pHostName, certPEM ))) return err;
if (P6FAILED( err = savePrivKeyInStore( (*ppKeystore), P6TEXT("p6r.clientauth"), m_pHostName, privPEM, privSize ))) return err;
return eOk;
}
P6CLASSMETHODIMPL CKmipExample1::getRNG(P6R::p6IRandom **ppRandom)
{
P6ERR err = eOk;
p6ComPtr<p6IRunningIface> cpRIT(IID_p6IRunningIface,&err);
if(P6SUCCEEDED(err)) {
if(P6FAILED(cpRIT->findInterfaceByString(P6_ENTROPY_SERVICE_INTERFACE,VALIDATEIF(p6IRandom,ppRandom)))) {
if(P6SUCCEEDED(err = p6CreateCryptoInstance(CID_p6EntropySource,VALIDATECOMPTR(p6IEntropySource,cpSource)))) {
if(P6SUCCEEDED(err = cpSource->initialize( P6ENTROPY_HIGH ))) {
if(P6SUCCEEDED(err = p6CreateCryptoInstance(CID_p6Random,VALIDATECOMPTR(p6IRandomInit,cpInit)))) {
if(P6SUCCEEDED(err = cpInit->initialize(P6RAND_NOFLAGS,cpSource))) {
err = cpInit.queryInterface(VALIDATEIF(p6IRandom,ppRandom));
}
}
}
}
}
}
else {
if(P6SUCCEEDED(err = p6CreateCryptoInstance(CID_p6EntropySource,VALIDATECOMPTR(p6IEntropySource,cpSource)))) {
if(P6SUCCEEDED(err = cpSource->initialize( P6ENTROPY_HIGH ))) {
if(P6SUCCEEDED(err = p6CreateCryptoInstance(CID_p6Random,VALIDATECOMPTR(p6IRandomInit,cpInit)))) {
if(P6SUCCEEDED(err = cpInit->initialize(P6RAND_NOFLAGS,cpSource))) {
err = cpInit.queryInterface(VALIDATEIF(p6IRandom,ppRandom));
}
}
}
}
}
return err;
}
// Replace the host name of "fqdn.com" to the fully qualified domain name of the server you wish to connect to.
P6R::P6ERR CKmipExample1::initialize()
{
P6ERR err = eOk;
P6WCHAR dbPath[P6MAXPATH+200] = {0};
if (P6FAILED( err = p6GetRuntimeIface (VALIDATECOMPTR( p6ISafeString, m_cpStr )))) return err;
if (P6FAILED( err = p6CreateInstance(NULL, CID_p6Dir, VALIDATECOMPTR(p6IDir, cpDir)))) return err;
if (P6FAILED( err = cpDir->initialize())) return err;
if(P6FAILED(err = getRNG(m_cpRandom.addressof()))) return err;
// -> right now configuration is hard coded, but could read out of a config file later
// m_compatMask is set to zero for TTLV message encoding , set to 2 for XML message encoding, and set to 4 for JSON message encoding
//
m_port = 5696;
m_compatMask = 0;
if (P6FAILED( err = m_cpStr->wstrdup( P6TEXT("fqdn.com"), &m_pHostName ))) return err;
// -> create one random number generator for all our tests
//if (P6FAILED(err = getRNG( &m_cpRandom ))) return err;
if (P6SUCCEEDED( err = getIGenKeys( cpGenKey.addressof() )))
{
err = cpGenKey->genSymmetricKey( m_cpSignKey.addressof(), 256, P6FALSE );
if (P6SUCCEEDED( err )) {
err = cpGenKey->genSymmetricKey( cpKey.addressof(), 256, P6FALSE );
}
}
if (P6SUCCEEDED( err )) err = p6CreateCryptoInstance( CID_p6SymmetricCrypto, VALIDATECOMPTR( p6ISymmetricCrypto, m_cpCrypto ));
if (P6SUCCEEDED( err )) err = m_cpCrypto->initialize( P6SYM_NOPADDING, CIPHER_AES_CFB );
if (P6SUCCEEDED( err )) err = m_cpCrypto->setKey( cpKey );
// -> initialize the keystore with keys provided to us by the server vendor
dbPath[0] = P6CHAR('\0');
if (P6FAILED( err = p6GetDirectory( P6D_DATA, dbPath, P6MAXPATH, NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( dbPath, P6CNTOF(dbPath), P6TEXT("/db/KMIP12_keystore"), NULL ))) return err;
cpDir->unlink( dbPath );
dbPath[0] = P6CHAR('\0');
if (P6FAILED( err = p6GetDirectory( P6D_DATA, dbPath, P6MAXPATH, NULL ))) return err;
if (P6FAILED( err = m_cpStr->wstrlcat( dbPath, P6CNTOF(dbPath), P6TEXT("/db/KMIP12_keystore.sig"), NULL ))) return err;
cpDir->unlink( dbPath );
err = createKeystore( P6TEXT("KMIP12_keystore"), P6TEXT("RootCert.pem"), P6TEXT("ClientCert.pem"), P6TEXT("ClientPrivate.pem"), 2048, m_cpStoreInit.addressof(), m_cpKeystore.addressof() );
return err;
}
// The client creates an SSL connection to the KMIP server and then makes its requests
// Configure the client on how it is supposed to behave (e.g., protocol version, use TTLV or XML or JSON).
//
P6CLASSMETHODIMPL CKmipExample1::setPreferences( P6KMIP_PREF* pPrefs, P6WCHAR* pLogDir, P6UINT16 asynchronous, P6UINT32 privateKeyEncoding, P6UINT32 publicKeyEncoding,
P6UINT32 symmetricKeyEncoding, P6UINT32 maxBufferSize, P6UINT32 connectTimeout, P6UINT32 sendTimeout, P6UINT32 receiveTimeout,
P6UINT32 initialBufCount, P6UINT32 growBufsBy )
{
m_cpStr->setMem( pPrefs, 0, sizeof( P6KMIP_PREF ));
pPrefs->pVersion = "1.2"; pPrefs->pSubdirectory = pLogDir;
pPrefs->asynchronous = asynchronous; pPrefs->maxBufferSize = maxBufferSize;
pPrefs->connectTimeout = connectTimeout; pPrefs->sendTimeout = sendTimeout;
pPrefs->receiveTimeout = receiveTimeout; pPrefs->initialBufCount = initialBufCount;
pPrefs->growBufsBy = growBufsBy; pPrefs->privateKeyEncoding = privateKeyEncoding;
pPrefs->publicKeyEncoding = publicKeyEncoding; pPrefs->symmetricKeyEncoding = symmetricKeyEncoding;
pPrefs->compatibility1 = m_compatMask;
return eOk;
}
// We just hard code the credentials for a test if needed
P6CLASSMETHODIMPL CKmipExample1::createSession( p6IKMIPClient* pClient, P6BOOL bWithCredentials )
{
P6KMIP_CREDENTIAL credential;
P6ERR err = eOk;
// -> integration testing setups are not production so QuintessenceLabs has a non-secure setup
if (P6FAILED( err = pClient->setSSLOptions( NULL, (P6SSF_METHOD_TLS1 | P6SSF_SECURE_CLIENT | P6SSF_SECURE_CLIENT_AUTH | P6SSF_LOG_X509SUBJECTLOOKUPS | P6SSF_VRFY_DISABLEHOSTMATCH)))) return err;
m_cpStr->setMem( &credential, 0, sizeof( P6KMIP_CREDENTIAL ));
credential.type = 1;
credential.value.password.userName.pString = "Fred";
credential.value.password.userName.length = 4;
credential.value.password.password.pString = "password1";
credential.value.password.password.length = 9;
return pClient->open( m_pHostName, m_port, (bWithCredentials ? &credential : NULL));
}
// Just return the very first unique identifier from the enumerator
P6CLASSMETHODIMPL CKmipExample1::extractUniqueId( p6IKMIPStr* pEnum, P6NCSTR* pUniqueId )
{
P6CHAR* pGUID = NULL;
P6NCSTR buffer = { NULL, 0 };
P6ERR err = eOk;
pUniqueId->pString = NULL;
pUniqueId->length = 0;
err = pEnum->reset();
err = pEnum->next( &buffer );
if ( 0 < buffer.length )
{
if (NULL == (pGUID = new(std::nothrow) P6CHAR[buffer.length + 2])) return eNoMemory;
pGUID[0] = 0;
buffer.pString = pGUID;
buffer.length += 2;
if (P6FAILED( err = pEnum->next( &buffer ))) return err;
pUniqueId->pString = buffer.pString;
pUniqueId->length = buffer.length;
}
else err = eFail;
return err;
}
// Have the KMIP server create a symmetric key and return its unique identifier.
// Main client function
// KMIP_TC_311_12
//
P6CLASSMETHODIMPL CKmipExample1::run( p6IDataStream *pStreamDebug )
{
P6KMIP_PREF preferences;
P6KMIP_RESULT resultCodes;
P6KMIP_KEYPARAMS keyParams;
P6KMIP_ATTRIBUTE attributeList[4];
P6NCSTR keyId = {NULL, 0};
P6ERR err = eOk;
// [1] Initialize
if (P6FAILED( err = p6CreateInstance( NULL, CID_p6KMIPClient, VALIDATECOMPTR( p6IKMIPClient, cpClient )))) return err;
setPreferences( &preferences, P6TEXT("TC_311_12"), 0, 0, 0, 0, 5000, 2000, 2000, 120000, 2, 2 );
err = cpClient->initialize( (P6KMIPFLG_TRACE_MSGS | P6KMIPFLG_TRACE_FORMATKMIPXML), m_cpKeystore, preferences );
// [2] Open a connection to the KMIP server via SSL
if (P6FAILED( err = createSession( cpClient, P6FALSE ))) { return err; }
// [3] Build the request (in this case a TTLV message), requesting a symmetric AES, 128 key to be created
m_cpStr->setMem( &resultCodes, 0, sizeof( P6KMIP_RESULT ));
m_cpStr->setMem( &newKey, 0, sizeof( P6KMIP_NEWOBJECT ));
m_cpStr->setMem( &keyParams, 0, sizeof( P6KMIP_KEYPARAMS ));
m_cpStr->setMem( &attributes, 0, sizeof( P6KMIP_TEMPLATEATTRIBUTE ));
attributeList[0].type = KMIP_ATTRIB_CRYPTOALGORITHM;
attributeList[0].index = 0;
attributeList[0].value.cryptoAlgorithm = KMIP_AES;
attributeList[1].type = KMIP_ATTRIB_CRYPTOLENGTH;
attributeList[1].index = 0;
attributeList[1].value.cryptoLength = 128;
attributeList[2].type = KMIP_ATTRIB_CRYPTOUSAGEMASK;
attributeList[2].index = 0;
attributeList[3].type = KMIP_ATTRIB_EXTENSION;
attributeList[3].index = 0;
attributeList[3].value.extension.xName.pString = "x-ID";
attributeList[3].value.extension.xName.length = 4;
attributeList[3].value.extension.xValue.vText.pString = "TC-311-12";
attributeList[3].value.extension.xValue.vText.length = 9;
attributes.attribCount = 4;
attributes.pAttributeList = attributeList;
keyParams.pAttributes = &attributes;
if (P6FAILED(err = cpClient->createKeyObject( keyParams, &newKey, &resultCodes ))) {
printf("\ncall to createKeyObject has failed %x\n", err );
}
else if (KMIP_RESULT_SUCCESS != resultCodes.resultStatus) {
printf("\nKMIP server returned an error\n");
}
// [4] Assuming the createKeyObject worked, extract the key's unique identifier from the enumerator
if (NULL != newKey.pUniqueId)
{
err = extractUniqueId( newKey.pUniqueId, &keyId );
newKey.pUniqueId->release();
newKey.pUniqueId = NULL;
}
// [5] If the key was created we need to clean up and remove it from the KMIP server
if (NULL != keyId.pString)
{
m_cpStr->setMem( &resultCodes, 0, sizeof( P6KMIP_RESULT ));
err = cpClient->destroyObject( keyId, NULL, &newKey.pUniqueId, &resultCodes );
if (P6FAILED( err )) {
printf("\ndestroying key call has failed\n");
}
else if (KMIP_RESULT_SUCCESS != resultCodes.resultStatus) {
printf("\nKMIP server returned an error\n");
}
delete [] keyId.pString;
}
return cpClient->close();
}
P6VOID KMIP_TC_311_12(P6R::p6IDataStream *pDataStream)
{
CKmipExample1 example;
P6CHAR szTmp[32];
P6ERR err = eOk;
if(P6SUCCEEDED(err = example.initialize())) {
err = example.run(pDataStream);
}
printf( "KMIP client result: [ %s ]\n", p6ErrToStr(err, &szTmp[0], P6CHARCNT(szTmp)) );
}
} // namespace
int main(int argc,char *argv[])
{
P6ERR err = eOk;
if ( P6SUCCEEDED( err = P6EXAMPLES::CConsoleStream::createInstance( NULL, VALIDATECOMPTR( p6IDataStream, cpDataStream ))))
{
if ( P6SUCCEEDED( err = p6InitializeLoader( cpDataStream, 9, P6SCLF_ALLLOG )))
{
KMIP_TC_311_12(cpDataStream);
}
else printf("ERROR: Failed to initialize the loader [ %x ]\n", err );
}
else printf( "ERROR: Failed to create CConsoleStream [ %x ]\n", err );
return err;
}