Extract certificates from provisioned devices
Extract certificates via API
Extracting keys and certificates through the Guardian API consists of using the Guardian Library to complete the two certificate and key extraction steps.
C# example
public static void GetKeyAndCerts()
{
medcrypt.guardian.InitializeFiles initializeFiles =
new medcrypt.guardian.InitializeFiles();
/* read provisioned files into file structure */
initializeFiles.trustStore =
File.ReadAllBytes(@"TrustStore.mcts");
initializeFiles.privateIdentity =
File.ReadAllBytes(@"PrivateIdentity.mcpi");
initializeFiles.certifiedProfile =
File.ReadAllBytes(@"CertifiedProfile.mcp");
/* customer data about the provisioning system */
string componentHandle = "my_component_handle";
string hardwareId = "my_serial_number";
string serviceName = "my_service_name";
/* accept input options, or create default */
medcrypt.guardian.InitializeOptions options =
new medcrypt.guardian.InitializeOptions();
/* initialize guardian for configured operations (key and cert)*/
medcrypt.guardian.Guardian gdn = new medcrypt.guardian.Guardian();
gdn.Initialize(
initializeFiles,
componentHandle,
hardwareId,
new medcrypt.guardian.InitializeOptions());
List<byte[]> certs = null;
byte[] key = null;
medcrypt.guardian.IService service = gdn.FindService(serviceName);
/* get key */
key = service.GetCertificateKey(KeyFormat.PKCS8_PEM);
/* get length of certificate chain, and add all certs to output
list */
ulong chainLen = service.GetCertificateChainLength();
certs = new List<byte[]>();
for (ulong i = 0; i < chainLen; i++)
{
certs.Add(service.GetCertificate(i, CertFormat.PEM));
}
}
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_KEY_SIZE 128
#define ARBITRARY_CERT_SIZE 3 * 1024
bool GetKeyAndCerts()
{
medcrypt::guardian::Status status;
medcrypt::guardian::utilities::InitializeFiles in_files;
std::string in_component_handle = "my_component_handle";
std::string in_hardware_id = "my_serial_number";
std::string in_provisioning_profile_folder =
"/path/to/provisioned/profile/folder/";
std::string in_service_name = "my_service_name";
/* initialize provided guardian */
medcrypt::guardian::Guardian guardian;
status = guardian.Initialize(
in_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;
}
std::unique_ptr<medcrypt::guardian::Service> service;
/* find desired service by name */
status = guardian.FindService(in_service_name.c_str(), &service);
/* check and print non OK error code */
if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
MSG_ERROR(("could not find service [%s] [%s]",
in_service_name.c_str(),
medcrypt::guardian::GuardianStatusEnum::NameOf(
EXTRACT_STATUS(status)).c_str()));
return false;
}
std::list<std::vector<char>> io_certs;
std::vector<unsigned char> io_key;
io_key.assign(ARBITRARY_KEY_SIZE, '\0');
size_t size = io_key.size();
/* retrieve pkcs8 encoded key */
status = service->GetCertificateKey(io_key.data(), &size);
if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
MSG_ERROR(("could not retrieve key [%s]",
medcrypt::guardian::GuardianStatusEnum::NameOf(
EXTRACT_STATUS(status)).c_str()));
return false;
}
io_key.resize(size);
/* retrieve any available certs from the cert chain */
size_t chain_length = service->GetCertificateChainLength();
io_certs.clear();
for (size_t i = 0; i < chain_length; i++) {
io_certs.emplace_back();
size = service->GetCertificateSize(i);
io_certs.back().assign(size, '\0');
/* retrieve certificate */
status = service->GetCertificate(
i,
io_certs.back().data(),
&size);
if (EXTRACT_STATUS(status) != medcrypt::guardian::GuardianStatusEnum::OK) {
MSG_ERROR(("could not retrieve cert [%u] [%s]",
(unsigned int)i,
medcrypt::guardian::GuardianStatusEnum::NameOf(
EXTRACT_STATUS(status)).c_str()));
return false;
}
}
return true;
}
C example
#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 */
#define ARBITRARY_KEY_SIZE 128
#define ARBITRARY_CERT_SIZE 3 * 1024
#define LEAF_CERT_IDX 0
/* Setup example write callback to be used by guardian streams */
static bool sample_callback(mcg_guardian_ostream_t *stream,
const uint8_t *buf,
size_t count)
{
size_t i;
uint8_t *dest = (uint8_t*)stream->state;
stream->state = dest + count;
for (i = 0; i < count; i++)
dest[i] = buf[i];
return true;
}
static bool get_key_and_certs()
{
mcg_status status = MCG_STATUS_FAIL;
mcg_initialize_options_t init_options = {0};
mcg_initialize_files_t init_files;
mcg_guardian_istream_t ts, pi, cp;
size_t cert_chain_path_length = 0;
size_t cert_chain_length = 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};
mcg_memory.mem = &memory_buffer[0];
mcg_memory.size = sizeof(memory_buffer);
/* customer data about this provisioning system */
char component_handle[] = "my_component";
char hardware_id[] = "my_serial_number";
char service_name[] = "my_service";
/* 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[ARBITRARY_BUF_SIZE] = {0};
size_t in_cp_len = 1234;
/* output buffers */
uint8_t io_key_buf[ARBITRARY_BUF_SIZE] = {0};
size_t io_key_buf_len = sizeof(io_key_buf);
uint8_t io_cert_buf[ARBITRARY_BUF_SIZE] = {0};
size_t io_cert_buf_len = sizeof(io_cert_buf);
mcg_guardian_ostream_t out_key;
mcg_guardian_ostream_t out_cert;
/* Create streams from provided ts/pi/cp byte buffers */
ts = mcg_istream_from_buffer((const uint8_t*)in_ts, in_ts_len);
pi = mcg_istream_from_buffer((const uint8_t*)in_pi, in_pi_len);
cp = mcg_istream_from_buffer((const uint8_t*)in_cp, in_cp_len);
/* Load streams into mcg_initialize_files_t */
init_files.trust_store = &ts;
init_files.private_identity = π
init_files.certified_profile = &cp;
status = mcg_gdn_initialize(
&mcg_memory,
&init_files,
component_handle,
hardware_id,
&init_options);
if (status)
{
/* Return failure */
return false;
}
/* setup buffer backed key output stream */
out_key.write_callback = &sample_callback;
out_key.max_size = io_key_buf_len;
out_key.bytes_written = 0;
out_key.state = io_key_buf;
status = mcg_gdn_write_key(&mcg_memory,
service_name,
true, /* true = PEM, false = DER */
&out_key);
if (status)
{
printf("Failed to write key");
return false;
}
/* setup buffer backed single cert output stream */
out_cert.write_callback = &sample_callback;
out_cert.max_size = io_cert_buf_len;
out_cert.bytes_written = 0;
out_cert.state = io_cert_buf;
status = mcg_gdn_write_cert(&mcg_memory,
service_name,
LEAF_CERT_IDX, /* Note: Only writes a single certificate */
true, /* true = PEM, false = DER */
&out_cert);
if (status)
{
printf("Failed to write cert");
return false;
}
return true;
}
Extract certificates via command line
This covers how to use a provisioned device to extract pre-arranged keys and certificates from that device's certified profile (CP). Extracting certificates via the command line consists of using the mcguard_cert_extract
utility to complete the the following certificate and key extraction steps:
Initialize Guardian with the device's certified profile.
Extract key and desired certificates.
All command line utilities use a working directory approach. During certificate extraction the
mcguard_cert_extract
utility expects to see a.mcts
,.mcpip
and.mcpp
file in the working directory.Any argument inside <> brackets should be replaced with the indicated input data (e.g., If the component handle is device1
<my_component>
, this could be replaced bydevice1
).
# Syntax
./mcguard_cert_extract --component <my_component> --hardware-id <my_hardwareid> --service <my_service> --key-dir <key_output_dir> --cert-dir <cert_output_dir> <path to provisioned profile>
# Example
./mcguard_cert_extract --component my_device --hardware-id my_device_001 --service my_service --key-dir /home/user/guardian/keys --cert-dir /home/user/guardian/certs /home/user/guardian/provisioned_profile
Last updated
Was this helpful?