As CICM has matured, there has been more interest in seeing CICM implementations. Given that IETF runs on "rough consensus and running code" attached is an initial C++ "Test Harness" which is a rough shell of an prototype CICM implementation. (If we can get an IETF SVN repository set up, we'll move this code over there.)
We invite all crypto module developers to take a look at the harness and
consider
implementing it for their devices. Note that the harness is meant to
demonstrate a
tiny subset of CICM: just basic encryption and decryption with a symmetric key.
Here are the descriptions of the attached files:
config.h - macro definitions for configuration parameters (identifiers,
payload, etc.)
cicm.h - header file for the test harness (includes references to the CICM
specification)
cicm.cpp - the CICM implementation (stub code; implementation work goes here)
encrypt.cpp - the encrypt portion of the test harness
decrypt.cpp - the decrypt portion of the test harness
Makefile - for use with make (assumes g++ for the compiler; edit as needed)
The following is a quick summary of the test harness scenario.
Encrypt:
1. Retrieve the module with the id {as configured}.
2. Select the symmetric key manager.
3. Select the symmetric key with the id {as configured}.
4. Select the channel manager.
5. Create an encrypt channel that uses an algorithm {as configured}.
6. Use the channel to encrypt and send a payload {as configured}.
Decrypt:
(Steps 1 - 3 above)
7. Select the channel manager. (For this test, this is the same as Step 4
above).
8. Create a decrypt channel that uses the same algorithm {as configured in step
5}.
9. Block until ready to receive payload.
10. Verify that the result from step 9 is the same as the payload used in step
6.
Corrections to the test harness should be sent to the list.
Have a good weekend,
Lev
/** Configuration macros. @todo Replace the values below, as needed. @file config.h @version 0.1 @date 2011-03-04 */ #define V_MODULE_ID "module-id" #define V_KEY_ID "symkey-id" #define V_ALGORITHM "algorithm" #define V_PAYLOAD "payload" #define V_PAYLOAD_LEN 7 #define V_PORT_ENCRYPT 42 #define V_PORT_DECRYPT 42
#include <stdint.h> /** Header file for the encrypt/decrypt test harness CICM library. @file CICM.h @version 0.1 @date 2011-03-04 @see http://tools.ietf.org/html/draft-lanz-cicm @see http://tools.ietf.org/html/draft-lanz-cicm-mm @see http://tools.ietf.org/html/draft-lanz-cicm-km @see http://tools.ietf.org/html/draft-lanz-cicm-cm */ namespace CICM { typedef uint32_t UInt32; /** @see CICM 2.2.1 */ typedef UInt32 Status; /** @see CICM 2.2.3 */ typedef UInt32 RemotePort; /** @see CICM 2.2.5 */ typedef char * CharString; /** @see CICM 2.2.1 */ typedef CharString ModuleId; /** @see CICM 2.2.2 */ typedef CharString KeyId; /** @see CICM-KM 3.6 */ typedef CharString SymEncrAlgorithmId; /** @see CICM-CM 4.1 */ /** @see CICM Appendix A. Status Codes */ const CICM::Status S_OK = 0x00000000; /** @see CICM 2.2.1 @see http://www.omg.org/spec/CPP/1.2/PDF */ class Buffer { private: unsigned long len; unsigned long *data; public: // Constructor Buffer(unsigned long len, char *data); // Destructor ~Buffer(void); // No Copy Constructor // Overloaded Operators Buffer & operator=(const Buffer &); Buffer & operator[](unsigned long idx); char * operator[](unsigned long idx) const; bool operator==(const Buffer &other) const; // Methods unsigned long length(void) const; char * get_buffer(void) const; }; //// Key Management //// /** @see CICM-KM 3.7 */ class Key {}; /** @see CICM-KM 5.2 */ class SymKey : CICM::Key {}; /** @see CICM-KM 5.1 */ class SymKeyManager { public: CICM::Status get_key_by_id( CICM::KeyId& key_id, // in CICM::SymKey** key_ref // out ); };//end: SymKeyManager //// Channel Management //// /** @see CICM-CM 4.5 */ class Channel {}; /** @see CICM-CM 4.7 */ class Controller : public CICM::Channel {}; /** @see CICM-CM 4.8 */ class Stream : public CICM::Channel {}; /** @see CICM-CM 4.6 */ class Conduit : public CICM::Controller, public CICM::Stream {}; /** @see CICM-CM 6.1 */ class WriteStream : public CICM::Stream {}; /** @see CICM-CM 6.2 */ class ReadStream : public CICM::Stream {}; /** @see CICM-CM 9*/ namespace Encrypt { /** @see CICM-CM 9.4 */ class Controller {}; /** @see CICM-CM 9.2 */ class Stream : public CICM::WriteStream { public: CICM::Status encrypt(CICM::Buffer*& buffer); };//end: CICM::Encrypt::Stream /** @see CICM-CM 9.6 */ class Conduit : public CICM::Conduit, public CICM::Encrypt::Controller, public CICM::Encrypt::Stream {}; /** @see CICM-CM 9.1 */ class ChannelManager { public: CICM::Status create_encrypt_conduit( CICM::RemotePort& remote_port, // in CICM::SymKey* key_ref, // in CICM::SymEncrAlgorithmId& algorithm, // in CICM::Encrypt::Conduit** conduit_ref // out ); };//end: CICM::Encrypt::ChannelManager };//end: CICM::Encrypt /** @see CICM-CM 10 */ namespace Decrypt { /** @see CICM-CM 10.4 */ class Controller {}; /** @see CICM-CM 10.2 */ class Stream : public CICM::ReadStream { public: CICM::Status decrypt(CICM::Buffer** buffer); };//end: CICM::Decrypt::Stream /** @see CICM-CM 10.6 */ class Conduit : public CICM::Conduit, public CICM::Decrypt::Controller, public CICM::Decrypt::Stream {}; /** @see CICM-CM 10.1 */ class ChannelManager { public: CICM::Status create_decrypt_conduit( CICM::RemotePort& remote_port, // in CICM::SymKey* key_ref, // in CICM::SymEncrAlgorithmId& algorithm, // in CICM::Decrypt::Conduit** conduit_ref // out ); };//end: CICM::Decrypt::ChannelManager };//end: CICM::Decrypt /** @see CICM-CM 4.4 */ class ChannelManager : public CICM::Encrypt::ChannelManager, public CICM::Decrypt::ChannelManager {}; //// Module Management //// /** @see CICM 2.3.2 */ class CryptoModule { public: CICM::SymKeyManager* _get_sym_key_manager(void); CICM::ChannelManager* _get_channel_manager(void); private: /** @see CICM 2.3.2.1 */ CICM::SymKeyManager sym_key_manager; CICM::ChannelManager channel_manager; };//end: CICM::CryptoModule /** @see CICM 2.3.1 */ class CICMRoot { public: CICM::Status get_module_by_id( CICM::ModuleId& module_id, // in CICM::CryptoModule** crypto_module_ref // out ); };//end: CICM::CICMRoot };//end: CICM
/**
Implementation of CICM backend.
@todo Complete the source code to operate with a specific cryptographic
device.
@file cicm.cpp
@version 0.1
@date 2011-03-04
*/
#include "cicm.h"
#include <iostream>
using namespace CICM;
/**
@todo Constructor for Buffer (IDL sequence<octet>).
*/
CICM::Buffer::Buffer(unsigned long len, char *data) {};
/**
@todo Destructor for Buffer (IDL sequence<octet>).
*/
CICM::Buffer::~Buffer() {};
/**
@todo Override equality operator.
*/
bool CICM::Buffer::operator==(const Buffer &other) const { return false; };
/**
@todo Return a reference to the module with the given module unique
identifier.
@class CICMRoot
@param [in] module_id
@param [out] crypto_module_ref
@return status code
@see http://tools.ietf.org/html/draft-lanz-cicm-02#section-2.3.1.1
*/
Status CICMRoot::get_module_by_id(
ModuleId& module_id, /* in */
CryptoModule** crypto_module_ref /* out */
) { return S_OK; };
/**
@todo Return a reference to CICM::SymKeyManager.
@class CryptoModule
@return a reference to the symmetric key manager
@see http://tools.ietf.org/html/draft-lanz-cicm-02#section-2.3.2.1
*/
SymKeyManager* CryptoModule::_get_sym_key_manager(void) {
return &(this->sym_key_manager);
};
/**
@todo Return a reference to CICM::ChannelManager.
@class CryptoModule
@return a reference to the channel manager
@see http://tools.ietf.org/html/draft-lanz-cicm-02#section-2.3.2.1
*/
ChannelManager* CryptoModule::_get_channel_manager(void) {
return &(this->channel_manager);
};
/**
@todo Return a reference to the symmetric key corresponding
to the specified infrastructure-specific identifier.
@class SymKeyManager
@param [in] key_id
@param [out] key_ref
@return status code
@see http://tools.ietf.org/html/draft-lanz-cicm-km-00#section-5.1.2
*/
Status SymKeyManager::get_key_by_id(
KeyId& key_id, /* in */
SymKey** key_ref /* out */
){ return S_OK; };
/**
@todo Create conduit to encrypt a stream of data.
@class Encrypt::ChannelManager
@param [in] remote_port
@param [in] key_ref
@param [in] algorithm
@param [out] conduit_ref
@return status code
@see http://tools.ietf.org/html/draft-lanz-cicm-cm-00#section-9.1.1
*/
Status Encrypt::ChannelManager::create_encrypt_conduit(
RemotePort& remote_port, /* in */
SymKey* key_ref, /* in */
SymEncrAlgorithmId& algorithm, /* in */
Encrypt::Conduit** conduit_ref /* out */
) { return S_OK; }
/**
@todo Sends data to the module to be encrypted.
The method blocks until data is sent.
@class Encrypt::Stream
@param [in] buffer
@return status code
@see http://tools.ietf.org/html/draft-lanz-cicm-cm-00#section-9.2.2
*/
Status Encrypt::Stream::encrypt(
Buffer*& buffer /* in */
) { return S_OK; }
/**
@todo Create conduit to decrypt a stream of data.
@class Decrypt::ChannelManager
@param [in] remote_port
@param [in] key_ref
@param [in] algorithm
@param [out] conduit_ref
@return status code
@see http://tools.ietf.org/html/draft-lanz-cicm-cm-00#section-10.1.1
*/
Status Decrypt::ChannelManager::create_decrypt_conduit(
RemotePort& remote_port, /* in */
SymKey* key_ref, /* in */
SymEncrAlgorithmId& algorithm, /* in */
Decrypt::Conduit** conduit_ref /* out */
) { return S_OK; }
/**
@todo Read plaintext data off of decrypt channel stream.
The method blocks until data becomes available.
@class Encrypt::Stream
@param [out] buffer
@return status code
@see http://tools.ietf.org/html/draft-lanz-cicm-cm-00#section-10.2.2
*/
Status Decrypt::Stream::decrypt(
Buffer** buffer /* out */
) { return S_OK; }
#include "config.h"
#include "cicm.cpp"
#include <iostream>
/**
Encrypt entry point. Executes steps 1 - 6 of the test harness scenario.
@file encrypt.cpp
@version 0.1
@date 2011-03-04
*/
int main() {
CICM::Status s;
CICM::CICMRoot *root = new CICM::CICMRoot();
CICM::ModuleId module_id = V_MODULE_ID;
CICM::CryptoModule *crypto_mod;
CICM::SymKeyManager *sym_key_manager;
CICM::KeyId key_id = V_KEY_ID;
CICM::SymKey *key;
CICM::ChannelManager *chan_manager;
CICM::RemotePort port = V_PORT_ENCRYPT;
CICM::SymEncrAlgorithmId algo = V_ALGORITHM;
CICM::Encrypt::Conduit *conduit;
CICM::Buffer *payload = new CICM::Buffer(V_PAYLOAD_LEN,
V_PAYLOAD);
// Step 1. Retrieve the module with the id {as configured}.
s = root->get_module_by_id(module_id, &crypto_mod);
if(S_OK == s) std::cout << "Step 1. Got the module." << std::endl;
// Step 2. Select the symmetric key manager.
sym_key_manager = crypto_mod->_get_sym_key_manager();
std::cout << "Step 2. Got the symmetric key manager." << std::endl;
// Step 3. Select the symmetric key with the id {as configured}.
s = sym_key_manager->get_key_by_id(key_id, &key);
if(S_OK == s) std::cout << "Step 3. Got the symmetric key." << std::endl;
// Step 4. Select the channel manager.
chan_manager = crypto_mod->_get_channel_manager();
std::cout << "Step 4. Got the channel manager." << std::endl;
// Step 5. Create an encrypt channel that uses an algorithm {as configured}.
s = chan_manager->create_encrypt_conduit(port, key, algo, &conduit);
if(S_OK == s) std::cout << "Step 5. Got the conduit." << std::endl;
// Step 6. Use the channel to encrypt and send a payload {as configured}.
s = conduit->encrypt(payload);
if(S_OK == s) std::cout << "Step 6. Encrypted the payload." << std::endl;
std::cout << "DONE - Encrypt" << std::endl;
return 0;
}
#include "config.h"
#include "cicm.cpp"
#include <iostream>
/**
Decrypt entry point. Executes steps 1 - 3 and 7 - 10 of the test harness
scenario.
@file decrypt.cpp
@version 0.1
@date 2011-03-04
*/
int main() {
CICM::Status s;
CICM::CICMRoot *root = new CICM::CICMRoot();
CICM::ModuleId module_id = V_MODULE_ID;
CICM::CryptoModule *crypto_mod;
CICM::SymKeyManager *sym_key_manager;
CICM::KeyId key_id = V_KEY_ID;
CICM::SymKey *key;
CICM::ChannelManager *chan_manager;
CICM::RemotePort port = V_PORT_DECRYPT;
CICM::SymEncrAlgorithmId algo = V_ALGORITHM;
CICM::Decrypt::Conduit *conduit;
CICM::Buffer *buf;
CICM::Buffer *payload = new CICM::Buffer(V_PAYLOAD_LEN,
V_PAYLOAD);
// Step 1. Retrieve the module with the id {as configured}.
s = root->get_module_by_id(module_id, &crypto_mod);
if(S_OK == s) std::cout << "Step 1. Got the module." << std::endl;
// Step 2. Select the symmetric key manager.
sym_key_manager = crypto_mod->_get_sym_key_manager();
std::cout << "Step 2. Got the symmetric key manager." << std::endl;
// Step 3. Select the symmetric key with the id {as configured}.
s = sym_key_manager->get_key_by_id(key_id, &key);
if(S_OK == s) std::cout << "Step 3. Got the symmetric key." << std::endl;
std::cout << "(Step 7 is next)" << std::endl;
// Step 7. Select the channel manager.
chan_manager = crypto_mod->_get_channel_manager();
std::cout << "Step 7. Got the channel manager." << std::endl;
// Step 8. Create a decrypt channel that uses the same algorithm {as
configured in step 5}.
s = chan_manager->create_decrypt_conduit(port, key, algo, &conduit);
if(S_OK == s) std::cout << "Step 8. Got the conduit." << std::endl;
// Step 9. Block until ready to receive payload.
s = conduit->decrypt(&buf);
if(S_OK == s) std::cout << "Step 9. Decrypted the payload." << std::endl;
// Step 10. Verify that the result from step 9 is the same as the payload
used in step 6.
std::cout << "Step 10. Payload "
<< ((*buf == *payload) ? "PASS" : "FAIL" ) << "." << std::endl;
std::cout << "DONE - Decrypt" << std::endl;
return 0;
}
Makefile
Description: Makefile
_______________________________________________ cicm mailing list [email protected] https://www.ietf.org/mailman/listinfo/cicm
