Device provisioning code examples

Disconnected provisioning examples

Guardian supports C#, C++, and C for disconnected provisioning.

C# example

public static void DisconnectedProvisioning()
{
    medcrypt.guardian.ProvisionFilesInput provisioningFilesInput =
        new medcrypt.guardian.ProvisionFilesInput();

    /* Customer data about the provisioning system */
    string componentHandle = "my_component_handle";
    string systemId = "my_system_name";
    string hardwareId = "my_serial_number";

    /* Load provisioning files to input file storage buffers */
    provisioningFilesInput.trustStore =
        File.ReadAllBytes(@"TrustStore.mcts");
    provisioningFilesInput.privateIdentity =
        File.ReadAllBytes(@"PrivateIdentity.mcpip");
    provisioningFilesInput.certifiedProfile =
        File.ReadAllBytes(@"CertifiedProvisioningProfile.mcpp");

    /* Create Guardian */
    medcrypt.guardian.Guardian gdn = new medcrypt.guardian.Guardian();

    /* Create default options */
    medcrypt.guardian.ProvisioningGenerateOptions options =
            new medcrypt.guardian.ProvisioningGenerateOptions();

    /* Call generate provision request */
    medcrypt.guardian.ProvisionFilesOutput provisioningOutputFiles =
        gdn.GenerateProvisionRequest(
            provisioningFilesInput,
            options,
            componentHandle,
            systemId,
            hardwareId);

    /* Persist provision request and generated private identity */
    File.WriteAllBytes(
        @"GeneratedPrivateIdentity.mcpi",
        provisioningOutputFiles.generatedPrivateIdentity);
    File.WriteAllBytes(
        @"ProvisionRequest.mcpr",
        provisioningOutputFiles.provisionRequest);
}

C++ example

#include "medcrypt/guardian/GuardianSystem.h"
#include "medcrypt/guardian/Utilities/Files/FileHelpers.h"

#define MSG(x) { printf x; printf("\n"); }
#define MSG_INFO(x) { MSG(x); }
#define MSG_ERROR(x) { printf("ERROR: "); MSG(x); }
#define MSG_WARNING(x) { printf("WARNING: "); MSG(x); }
#define ARBITRARY_BUF_SIZE 2 * 1024

static const char kPrFilename[] = "ProvisionRequest.mcpr";
static const char kPiFilename[] = "PrivateIdentity.mcpi";

static bool WriteBufferToFile(
    const std::string& in_filepath,
    const char* in_file_contents,
    const size_t in_file_size);

bool DisconnectedProvisioning()
{
    medcrypt::guardian::utilities::ProvisionFiles files;
    std::string in_component_handle = "my_component_handle";
    std::string in_hardware_id = "my_serial_number";
    std::string in_provisioning_profile_folder =
        "/home/user/guardian/profiles/initial_profile";

    /* Retrieve provisioning files, for an initial provision these are the actual provisioning profile files */
    if (!medcrypt::guardian::utilities::GetProvisionFilesFromPath(
            in_provisioning_profile_folder,
            true,
            &files)) {
        MSG_ERROR(("could not retrieve provisioning files"));
        return false;
    }

    /* Assign buffers to outputs */
    char pr_buf[ARBITRARY_BUF_SIZE] = {0};
    char gpi_buf[ARBITRARY_BUF_SIZE] = {0};

    files.ProvisionRequest = pr_buf;
    files.ProvisionRequestSize = sizeof(pr_buf);
    files.GeneratedPrivateIdentity = gpi_buf;
    files.GeneratedPrivateIdentitySize = sizeof(gpi_buf);

    /* Create Guardian */
    medcrypt::guardian::Guardian guardian;
    medcrypt::guardian::Status status;

    /* Accept input options, or create default, alias hardware id to system name, actually generate the provision request */
    status = guardian.GenerateProvisionRequest(
        files,
        medcrypt::guardian::ProvisioningGenerateOptions(),
        in_component_handle.c_str(),
        in_hardware_id.c_str(),
        in_hardware_id.c_str());

    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not generate provision request [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Write the provision request to disk */
    if (!WriteBufferToFile(
            in_provisioning_profile_folder + kPrFilename,
            files.ProvisionRequest,
            files.ProvisionRequestSize))
    {
        MSG_ERROR(("could not write generated provision request"));
        return false;
    }

    /* Write the private identity to disk */
    if (!WriteBufferToFile(
            in_provisioning_profile_folder + kPiFilename,
            files.GeneratedPrivateIdentity,
            files.GeneratedPrivateIdentitySize))
    {
        MSG_ERROR(("could not write generated private identity"));
        return false;
    }

    return true;
}

static bool
WriteBufferToFile(
    const std::string& in_filepath,
    const char* in_file_contents,
    const size_t in_file_size)
{
    bool return_value = false;

    std::ofstream output(in_filepath, std::ios::binary);
    if( output.good() &&
        in_file_size <= (std::numeric_limits<std::streamsize>::max)())
    {
        output.write(in_file_contents, static_cast<std::streamsize>(in_file_size));
        output.close();
        return_value = true;
    }

    return return_value;
}

C example

The C interface uses streams for all large inputs and outputs. The example below will show these streams backed by buffers. Output buffers will be arbitrarily sized.

#define MAX_GDN_SIZE 15 * 1024 /* Increase as necessary, this memory does not have to be on the stack */
#define ARBITRARY_BUF_SIZE 5 * 1024 /* Increase as necessary */

static bool disconnected_provisioning()
{
    mcg_status status = 0;
    /* Create Guardian memory region, this memory can come from any source but must be a continuous block */
    mcg_memory_t mcg_memory = {NULL, 0, 0};
    uint8_t memory_buffer[MAX_GDN_SIZE] = {0};

    /* Initialize file pointer storage structs along with input and output streams */
    mcg_provision_files_t prov_files = {0};
    mcg_provisioning_generate_options_t p_options = {0};
    mcg_guardian_istream_t ts, pi, cp;
    mcg_guardian_ostream_t pr = {0};
    mcg_guardian_ostream_t gpi = {0};

    /* Customer data about this provisioning system */
    char component_handle[] = "my_component";
    char system_name[] = "my_system_name";
    char hardware_id[] = "my_serial_number";

    mcg_memory.mem = &memory_buffer[0];
    mcg_memory.size = sizeof(memory_buffer);

    /* Read trust store into this buffer, and set in_ts_len to actual size */
    uint8_t in_ts[ARBITRARY_BUF_SIZE] = {0};
    size_t in_ts_len = 1234;

    /* Read private identity into this buffer, and set in_pi_len to actual size */
    uint8_t in_pi[ARBITRARY_BUF_SIZE] = {0};
    size_t in_pi_len = 1234;

    /* Read certified profile into this buffer, and set in_cp_len to actual size */
    uint8_t in_cp_prov[ARBITRARY_BUF_SIZE] = {0};
    size_t in_cp_prov_len = 1234;

    /* Allocate memory for provision request and generated private identity output */
    uint8_t io_pr[ARBITRARY_BUF_SIZE] = {0};
    size_t io_pr_len = sizeof(pr);
    uint8_t io_gpi[ARBITRARY_BUF_SIZE] = {0};
    size_t io_gpi_len = sizeof(gpi);

    /* Create streams from provided ts/pi/cp byte buffers */
    ts = mcg_istream_from_buffer(in_ts, in_ts_len);
    pi = mcg_istream_from_buffer(in_pi, in_pi_len);
    cp = mcg_istream_from_buffer(in_cp_prov, in_cp_prov_len);

    /* Create output streams for provision request and generated private
        identity */
    pr = mcg_ostream_from_buffer(io_pr, io_pr_len);
    gpi = mcg_ostream_from_buffer(io_gpi, io_gpi_len);

    /* Load streams into mcg_provision_files_t */
    prov_files.trust_store = &ts;
    prov_files.private_identity = &pi;
    prov_files.certified_profile = &cp;
    prov_files.provision_request = &pr;
    prov_files.generated_private_identity = &gpi;

    status = mcg_gdn_generate_provision_request(&mcg_memory,
            &prov_files,
            &p_options,
            component_handle,
            system_name,
            hardware_id);

    if (status != MCG_STATUS_OK) {
        return false;
    }

    io_pr_len = pr.bytes_written;
    io_gpi_len = gpi.bytes_written;

    /* Persist PR (io_pr/io_pr_len) and GPI (io_gpi/io_gpi_len) to storage */

    return true;
}

Connected device provisioning examples

Guardian supports C# and C++ for connected provisioning.

C# example

public static void ConnectedProvisioning()
{
    public static void ConnectedProvisioning()
{
    medcrypt.guardian.ProvisionFilesInput provisioningFilesInput =
            new medcrypt.guardian.ProvisionFilesInput();
        medcrypt.guardian.ProvisionFilesOutput provisioningOutputFiles =
            new medcrypt.guardian.ProvisionFilesOutput();
    // Complete Disconnected Provisioning as in DisconnectedProvisioning()
    // The data in provisioningFilesInput and provisioningOutputFiles should
    // come from the DisconnectedProvisioning() function.
    //
    // The static text is reproduced in this function for readability.
    string componentHandle = "my_component_handle";
    string hardwareId = "my_serial_number";

    /* copy provisioning profile files to initialization file storage */
    medcrypt.guardian.InitializeFiles initializeFiles =
        new medcrypt.guardian.InitializeFiles();
    initializeFiles.trustStore = provisioningFilesInput.trustStore;
    initializeFiles.privateIdentity = provisioningFilesInput.privateIdentity;
    initializeFiles.certifiedProfile = provisioningFilesInput.certifiedProfile;

    /* initialize guardian for configured operations (connecting to backend)*/
    medcrypt.guardian.Guardian gdn = new medcrypt.guardian.Guardian();

    gdn.Initialize(
        initializeFiles,
        componentHandle,
        hardwareId,
        new medcrypt.guardian.InitializeOptions());

    /* create default options */
    medcrypt.guardian.ProvisioningOnlineOptions options =
            new medcrypt.guardian.ProvisioningOnlineOptions();

    /* load provision request into online files structure */
    medcrypt.guardian.ProvisioningFilesOnline onlineFiles =
        new medcrypt.guardian.ProvisioningFilesOnline();
    onlineFiles.provisionRequest =
        provisioningOutputFiles.provisionRequest;

    /* start connected provisioning state machine */
    gdn.StartProvisioningOnline(onlineFiles, options);
    gdn.Run();

    /* wait for provisioning to complete, error, or timeout to occur */
    DateTime start = DateTime.Now;
    TimeSpan timeout = TimeSpan.FromMinutes(2);
    while (gdn.IsProvisioningRunning() &&
            System.DateTime.Now - start < timeout)
    {
        gdn.Run();
        System.Threading.Thread.Sleep(500);
    }

    /* persist provisioned profile */
    File.WriteAllBytes(
        @"CertifiedProfile.mcp",
        gdn.GetProvisionedProfile());
}
}

C++ example

#define ARBITRARY_BUF_SIZE 10 * 1024

static const char kCpFilename[] = "CertifiedProfile.mcp";
bool ConnectedProvisioning()
{

    The static text is reproduced in this function for readability. */
    // Complete Disconnected Provisioning as in DisconnectedProvisioning()
    // The data in DisconnectedProvisioning()'s "files" object should be copied 
    // to "in_files" in this function.
    //
    // The static text is reproduced in this function for readability.
    medcrypt::guardian::utilities::ProvisionFiles in_files;
    std::string in_component_handle = "my_component_handle";
    std::string in_hardware_id = "my_serial_number";
    std::string in_provisioning_profile_folder = "/home/user/guardian/profiles/initial_profile";

     /* Create Guardian */
    medcrypt::guardian::Guardian guardian;
    medcrypt::guardian::Status status;

    /* Initialize Guardian with the provided provisioning profile to enable connecting to medcrypt backend infrastructure */
    medcrypt::guardian::utilities::InitializeFiles init_files;
    init_files.TrustStore           = in_files.TrustStore;
    init_files.TrustStoreSize       = in_files.TrustStoreSize;
    init_files.PrivateIdentity      = in_files.PrivateIdentity;
    init_files.PrivateIdentitySize  = in_files.PrivateIdentitySize;
    init_files.CertifiedProfile     = in_files.CertifiedProfile;
    init_files.CertifiedProfileSize = in_files.CertifiedProfileSize;

    /* Initialize provided Guardian */
    status = guardian.Initialize(
        init_files,
        in_component_handle.c_str(),
        in_hardware_id.c_str(),
        medcrypt::guardian::InitializeOptions());

    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not initialize guardian [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Start the internal online provisioning state machine by providing it with the generated provision request */
    medcrypt::guardian::utilities::ProvisionOnlineFiles online_files;
    online_files.ProvisionRequest       = in_files.ProvisionRequest;
    online_files.ProvisionRequestSize   = in_files.ProvisionRequestSize;

    status = guardian.StartProvisioningOnline(
        online_files,
        medcrypt::guardian::ProvisioningOptions());  
    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not start online provisioning [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Engage internal state machine */
    status = guardian.Run();
    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not run guardian [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Wait for provisioning to complete, error, or timeout to occur */
    auto start = std::chrono::steady_clock::now();
    auto timeout = std::chrono::minutes(2);
    while (guardian.IsProvisioningRunning() &&
                ((std::chrono::steady_clock::now() - start) < timeout)) {
            guardian.Run();
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    /* Retrieve the received provisioned profile */
    char profile[ARBITRARY_BUF_SIZE] = {0};
    size_t profile_size = sizeof(profile);
    status = guardian.GetProvisionedProfile(
            profile,
            &profile_size);
    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not complete online provisioning [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Write the provisioned profile to disk */
    if (!WriteBufferToFile(
            in_provisioning_profile_folder + kCpFilename,
            profile,
            profile_size))
    {
        MSG_ERROR(("could not write provisioned profile"));
        return false;
    }

    return true;
}

Proxy device provisioning examples

Guardian supports C# and C++ for proxy provisioning. Since Guardian does not support connected provisioning, it cannot proxy a provision request.

C# example

public static void ConnectedProvisioning()
{
    public static void ConnectedProvisioning()
{
    medcrypt.guardian.ProvisionFilesInput provisioningFilesInput =
            new medcrypt.guardian.ProvisionFilesInput();
        medcrypt.guardian.ProvisionFilesOutput provisioningOutputFiles =
            new medcrypt.guardian.ProvisionFilesOutput();
    // Complete Disconnected Provisioning as in DisconnectedProvisioning()
    // The data in provisioningFilesInput and provisioningOutputFiles should
    // come from the DisconnectedProvisioning() function.
    //
    // The static text is reproduced in this function for readability.
    string componentHandle = "my_component_handle";
    string hardwareId = "my_serial_number";

    /* Copy provisioning profile files to initialization file storage */
    medcrypt.guardian.InitializeFiles initializeFiles =
        new medcrypt.guardian.InitializeFiles();
    initializeFiles.trustStore = provisioningFilesInput.trustStore;
    initializeFiles.privateIdentity = provisioningFilesInput.privateIdentity;
    initializeFiles.certifiedProfile = provisioningFilesInput.certifiedProfile;

    /* Initialize Guardian for configured operations (connecting to backend)*/
    medcrypt.guardian.Guardian gdn = new medcrypt.guardian.Guardian();

    gdn.Initialize(
        initializeFiles,
        componentHandle,
        hardwareId,
        new medcrypt.guardian.InitializeOptions());

    /* Create default options */
    medcrypt.guardian.ProvisioningOnlineOptions options =
            new medcrypt.guardian.ProvisioningOnlineOptions();

    /* Load provision request into online files structure */
    medcrypt.guardian.ProvisioningFilesOnline onlineFiles =
        new medcrypt.guardian.ProvisioningFilesOnline();
    onlineFiles.provisionRequest =
        File.ReadAllBytes(@"ProxiedProvisionRequest.mcpr");

    /* Start connected provisioning state machine */
    gdn.StartProvisioningOnline(onlineFiles, options);
    gdn.Run();

    /* Wait for provisioning to complete, error, or timeout to occur */
    DateTime start = DateTime.Now;
    TimeSpan timeout = TimeSpan.FromMinutes(2);
    while (gdn.IsProvisioningRunning() &&
            System.DateTime.Now - start < timeout)
    {
        gdn.Run();
        System.Threading.Thread.Sleep(500);
    }

    /* Persist provisioned profile */
    File.WriteAllBytes(
        @"CertifiedProfile.mcp",
        gdn.GetProvisionedProfile());
}
}

C++ example

#define ARBITRARY_BUF_SIZE 10 * 1024

static const char kCpFilename[] = "CertifiedProfile.mcp";
bool ConnectedProvisioning()
{
    /* Complete Disconnected Provisioning as in DisconnectedProvisioning(). The data in from DisconnectedProvisioning()'s "files" object should be copied to "in_files" in this function.
    The static text is reproduced in this function for readability. */
    medcrypt::guardian::utilities::ProvisionFiles in_files;
    std::string in_component_handle = "my_component_handle";
    std::string in_hardware_id = "my_serial_number";
    std::string in_provisioning_profile_folder = "/home/user/guardian/profiles/initial_profile";

     /* Create Guardian */
    medcrypt::guardian::Guardian guardian;
    medcrypt::guardian::Status status;

    /* Initialize Guardian with the provided provisioning profile to enable connecting to medcrypt backend infrastructure */
    medcrypt::guardian::utilities::InitializeFiles init_files;
    init_files.TrustStore           = in_files.TrustStore;
    init_files.TrustStoreSize       = in_files.TrustStoreSize;
    init_files.PrivateIdentity      = in_files.PrivateIdentity;
    init_files.PrivateIdentitySize  = in_files.PrivateIdentitySize;
    init_files.CertifiedProfile     = in_files.CertifiedProfile;
    init_files.CertifiedProfileSize = in_files.CertifiedProfileSize;

    /* Initialize provided Guardian */
    status = guardian.Initialize(
        init_files,
        in_component_handle.c_str(),
        in_hardware_id.c_str(),
        medcrypt::guardian::InitializeOptions());

    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not initialize guardian [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Start the internal online provisioning state machine by providing it with the generated provision request */
    medcrypt::guardian::utilities::ProvisionOnlineFiles online_files;
    online_files.ProvisionRequest       = in_files.ProvisionRequest;
    online_files.ProvisionRequestSize   = in_files.ProvisionRequestSize;

    /* Load proxy Provision Request to a buffer and size here */
    char pr_buf[2048] = {0};
    size_t pr_buf_size = sizeof(buf);

    /* Start the internal online provisioning state machine by
    providing it with the generated disconnected provision request */
    medcrypt::guardian::utilities::ProvisionOnlineFiles online_files;
    online_files.ProvisionRequest       = pr_buf;
    online_files.ProvisionRequestSize   = pr_buf_size;

    status = guardian.StartProvisioningOnline(
        online_files,
        medcrypt::guardian::ProvisioningOptions());  
    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not start online provisioning [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Engage internal state machine */
    status = guardian.Run();
    /* Check and print non_OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not run guardian [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Wait for provisioning to complete, error, or timeout to occur */
    auto start = std::chrono::steady_clock::now();
    auto timeout = std::chrono::minutes(2);
    while (guardian.IsProvisioningRunning() &&
                ((std::chrono::steady_clock::now() - start) < timeout)) {
            guardian.Run();
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    /* Retrieve the received provisioned profile*/
    char profile[ARBITRARY_BUF_SIZE] = {0};
    size_t profile_size = sizeof(profile);
    status = guardian.GetProvisionedProfile(
            profile,
            &profile_size);
    /* Check and print non-OK error code */
    if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
        MSG_ERROR(("could not complete online provisioning [%s]",
            medcrypt::guardian::GuardianStatusEnum::NameOf(
                EXTRACT_STATUS(status)).c_str()));
        return false;
    }

    /* Write the provisioned profile to disk */
    if (!WriteBufferToFile(
            in_provisioning_profile_folder + kCpFilename,
            profile,
            profile_size))
    {
        MSG_ERROR(("could not write provisioned profile"));
        return false;
    }

    return true;
}

Last updated

Was this helpful?