A.2 Examination of personality attributes
The example below searches all attributes of a personality given by its name pers_name for an X.509 DeviceIdentity certificate.
bool b_loop_attr = true;
gta_enum_handle_t h_enum_attr = GTA_HANDLE_ENUM_FIRST;
while (b_loop_attr) {
char attr_name[STR_LEN_MAX];
char attr_type[STR_LEN_MAX];
myio_obufstream_t ostream_attr_name = { 0 };
myio_obufstream_t ostream_attr_type = { 0 };
myio_open_obufstream(&ostream_attr_name, attr_name,
sizeof(attr_name), &errinfo);
myio_open_obufstream(&ostream_attr_type, attr_type,
sizeof(attr_type), &errinfo);
if (gta_personality_attributes_enumerate(h_inst,
pers_name,
h_enum_attr,
(gtaio_ostream_t *)&ostream_attr_name,
(gtaio_ostream_t *)&ostream_attr_type,
&errinfo)) {
/* Get the attribute holding the
DeviceIdentity Certificate */
if (0 == strncmp(attr_type,
"ch.iec.30168.trustlist.certificate.self.x509",
STR_LEN_MAX)) {
h_ctx = gta_context_open(h_inst,
pers_name,
"org.opcfoundation.ECC-nistP256",
&errinfo);
/* get application certificate */
char devid_cert[CERT_SIZE_MAX];
myio_obufstream_t ostream_devid_cert = { 0 };
myio_open_obufstream(&ostream_devid_cert,
devid_cert, sizeof(devid_cert), &errinfo);
gta_personality_get_attribute(h_ctx,
attr_name, (gtaio_ostream_t *)&ostream_devid_cert,
&errinfo);
/* ... make use of this DeviceIdentity Cerficate
(e.g., add it to a list) ... */
gta_context_close(h_ctx, &errinfo);
}
}
else {
b_loop_attr = false;
}
myio_close_obufstream(&ostream_attr_name, &errinfo);
myio_close_obufstream(&ostream_attr_type, &errinfo);
}
Device onboarding for org.opcfoundation.ECC-nistP256The example code below illustrates the use of GTA API to implement the scenario outlined in section 5.2.3.1, Figure 12.
The following assumptions apply:
Identifier used for the DCA Personality Set isurn:manufacturer.com:2024-10:myproduct:SN51235
Name used for the DCA Identity Personality isurn:manufacturer.com:2024-10:myproduct:SN51235?cg=DefaultApplicationGroup&ct=EccNistP256&ix=1
Name used for the DCA TrustList Personality isurn:manufacturer.com:2024-10:myproduct:SN51235?cg=DefaultApplicationGroup
Note that the example can be easily adjusted for any other profile by just switching to another profile (e.g., org.opcfoundation.Aes256-Sha256-RsaPss) and adjusting the identifier and personality names as desired.
gta_errinfo_t errinfo = 0;
char identifier_value[]
= "urn:manufacturer.com:2024-10:myproduct:SN51235";
char personality_name[]
= "urn:manufacturer.com:2024-10:myproduct:SN51235?"
"cg=DefaultApplicationGroup&ct=EccNistP256&ix=1";
char identity_profile[]
= "org.opcfoundation.ECC-nistP256";
char application[] = "DCA Identity";
char trustlist_personality_name[]
= "urn:manufacturer.com:2024-10:myproduct:SN51235?"
"cg=DefaultApplicationGroup";
char trustlist_application[] = "DCA TrustList";
char trustlist_profile[]
= "ch.iec.30168.basic.local_data_integrity_only";
/* Assign identifier */
gta_identifier_assign(
h_inst,
"org.opcfoundation.application_instance_uri",
identifier_value,
&errinfo);
/* Create DCA Identity Personality */
gta_access_policy_handle_t h_auth_use = GTA_HANDLE_INVALID;
h_auth_use = gta_access_policy_simple(
h_inst,
GTA_ACCESS_DESCRIPTOR_TYPE_INITIAL,
&errinfo);
gta_access_policy_handle_t h_auth_use = GTA_HANDLE_INVALID;
h_auth_admin = gta_access_policy_simple(
h_inst,
GTA_ACCESS_DESCRIPTOR_TYPE_INITIAL,
&errinfo);
struct gta_protection_properties_t protection_props = {0};
gta_personality_create(
h_inst,
identifier_value,
personality_name,
application,
identity_profile,
h_auth_use,
h_auth_admin,
protection_props,
&errinfo);
/* Generate CSR */
gta_context_handle_t h_ctx = GTA_HANDLE_INVALID;
h_ctx = gta_context_open(
h_inst,
personality_name,
"com.github.generic-trust-anchor-api.basic.enroll",
&errinfo);
/* Set context attribute org.opcfoundation.csr.subject */
const char subject_der[] = {…};
size_t subject_der_len = …;
myio_ibufstream_t istream_subject = { 0 };
myio_open_ibufstream(
&istream_subject,
subject_der, subject_der_len,
&errinfo);
gta_context_set_attribute(
h_ctx,
"org.opcfoundation.csr.subject",
(gtaio_istream_t*)&istream_subject,
&errinfo);
myio_close_ibufstream(&istream_subject, &errinfo);
/* Set context attribute org.opcfoundation.csr.subjectAltName */
const char subject_alt_name_der[] = {…};
size_t subject_alt_name_der_len = …;
myio_ibufstream_t istream_subject_alt_name = { 0 };
myio_open_ibufstream(
&istream_subject_alt_name,
subject_alt_name_der, subject_alt_name_der_len,
&errinfo);
gta_context_set_attribute(
h_ctx,
"org.opcfoundation.csr.subjectAltName",
(gtaio_istream_t*)&istream_subject_alt_name,
&errinfo);
myio_close_ibufstream(&istream_subject_alt_name, &errinfo);
char csr_buffer[CSR_SIZE];
myio_obufstream_t ostream_csr = { 0 };
myio_open_obufstream(
&ostream_csr,
csr_buffer, sizeof(csr_buffer),
&errinfo);
gta_personality_enroll(
h_ctx,
(gtaio_ostream_t*)&ostream_csr,
&errinfo);
myio_close_obufstream(&ostream_csr, &errinfo);
/* Send CSR and receive certificate */
char cert_buffer[] = {…};
size_t cert_len = …;
/* Store DCA certificate (optional) */
myio_ibufstream_t istream_cert = { 0 };
myio_open_ibufstream(
&istream_cert,
cert_buffer, cert_len,
&errinfo);
gta_personality_add_attribute(
h_ctx,
"ch.iec.30168.trustlist.certificate.self.x509",
"DCA certificate",
(gtaio_istream_t*)&istream_cert,
&errinfo);
myio_close_ibufstream(&istream_cert, &errinfo);
gta_context_close(h_ctx, &errinfo);
/* Receive TrustList */
char trustlist_buffer[] = {…};
size_t trustlist_len = …;
/* Create DCA TrustList Personality */
gta_personality_create(
h_inst,
identifier_value,
trustlist_personality_name,
trustlist_application,
trustlist_profile,
h_auth_use,
h_auth_admin,
protection_props,
&errinfo);
/* Protect DCA TrustList objects */
gta_context_handle_t h_ctx_seal = GTA_HANDLE_INVALID;
h_ctx_seal = gta_context_open(
h_inst,
trustlist_personality_name,
trustlist_profile,
&errinfo);
myio_ibufstream_t istream_trustlist = { 0 };
myio_open_ibufstream(
&istream_trustlist,
trustlist_buffer, trustlist_len,
&errinfo);
#define INTEGRITY_PROTECTION_SEAL_LENGTH 32
char seal_buffer[INTEGRITY_PROTECTION_SEAL_LENGTH];
myio_obufstream_t ostream_seal = { 0 };
myio_open_obufstream(
&ostream_seal,
seal_buffer, sizeof(seal_buffer),
&errinfo);
gta_authenticate_data_detached(
h_ctx_seal,
(gtaio_istream_t*)&istream_trustlist,
(gtaio_ostream_t*)&ostream_seal,
&errinfo);
myio_close_ibufstream(&istream_trustlist, &errinfo);
myio_close_obufstream(&ostream_seal, &errinfo);
gta_context_close(h_ctx_seal, &errinfo);
Using org.opcfoundation.Aes256-Sha256-RsaPss to create a OpenSecureChannel ResponseThe example code below illustrates the use of GTA API to implement the scenario outlined in section 5.5.2, Figure 21. Note that functionality expected to be provided by the application is not elaborated but only addressed in comments. Error handling is omitted for the sake of clarity of the workflow.
The following pre-conditions apply:
OPC UA application installed on device
The OPC UA application has been successfully onboarded (cf. 5.4)
The OPC UA security policy used in OpenSecureChannel Response is Aes256-Sha256-RsaPss
The GTA API profile used in the example is org.opcfoundation.Aes256-Sha256-RsaPss
The name of the attribute used to store the Application Instance Certificate is my_server
The GTA API personality name used in the example is urn:manufacturer.com:2024-10:myproduct:myserver_appid?cg=DefaultApplicationGroup&ct=Rsa2048&ix=1gta_errinfo_t errinfo = 0;
char personality_name[]
= "urn:manufacturer.com:2024-10:myproduct:myserver_appid?"
"cg=DefaultApplicationGroup&ct=Rsa2048&ix=1";
char profile[]
= "org.opcfoundation.Aes256-Sha256-RsaPss";
char certificate_name = "my_server";
char trustlist_personality_name[]
= "urn:manufacturer.com:2024-10:myproduct:myserver_appid?"
"cg=DefaultApplicationGroup;
char trustlist_profile[]
= "ch.iec.30168.basic.local_data_integrity_only";
gta_context_handle_t h_ctx = GTA_HANDLE_INVALID;
h_ctx = gta_context_open(
h_inst,
personality_name,
profile,
&errinfo);
/* Get server certificate from personality attribute (optional) */
char cert_buffer[CERT_SIZE];
myio_obufstream_t ostream_cert = { 0 };
gta_personality_get_attribute(
h_ctx,
certificate_name,
(gtaio_ostream_t*)&ostream_cert,
&errinfo);
myio_close_obufstream(&ostream_cert, &errinfo);
/* Prepare OpenSecureChannel Response */
gta_context_handle_t h_ctx_seal = GTA_HANDLE_INVALID;
h_ctx_seal = gta_context_open(
h_inst,
trustlist_personality_name,
trustlist_profile,
&errinfo);
char trustlist_buffer[] = {…};
size_t trustlist_len = …;
myio_ibufstream_t istream_trustlist = { 0 };
myio_open_ibufstream(
&istream_trustlist,
trustlist_buffer, trustlist_len,
&errinfo);
char seal_buffer[] = {…};
size_t seal_len = …;
myio_ibufstream_t istream_seal = { 0 };
myio_open_ibufstream(
&istream_seal,
seal_buffer, seal_len,
&errinfo);
if (!gta_verify_data_detached(
h_ctx_seal,
(gtaio_istream_t*)&istream_trustlist,
(gtaio_istream_t*)&istream_seal,
&errinfo)) {
/* fail – TrustList has been tampered with */
}
myio_close_ibufstream(&istream_trustlist, &errinfo);
myio_close_ibufstream(&istream_seal, &errinfo);
gta_context_close(h_ctx_seal, &errinfo);
char encrypted_requestdata_buffer[] = {…};
size_t encrypted_requestdata_len = …;
myio_ibufstream_t istream_encrypted_requestdata = { 0 };
myio_open_ibufstream(
&istream_encrypted_requestdata,
encrypted_requestdata_buffer, encrypted_requestdata_len,
&errinfo);
#define REQUESTDATA_SIZE
char decrypted_requestdata_buffer[REQUESTDATA_SIZE];
myio_obufstream_t ostream_decrypted_requestdata = { 0 };
myio_open_obufstream(
&ostream_decrypted_requestdata,
decrypted_requestdata_buffer, sizeof(decrypted_requestdata_buffer),
&errinfo);
gta_unseal_data(
h_ctx,
(gtaio_istream_t*)&istream_encrypted_requestdata,
(gtaio_ostream_t*)&ostream_decrypted_requestdata,
&errinfo);
myio_close_ibufstream(&istream_encrypted_requestdata, &errinfo);
myio_close_obufstream(&ostream_decrypted_requestdata, &errinfo);
char tbs_responsedata_buffer[] = {…};
size_t tbs_responsedata_len = …;
myio_ibufstream_t istream_tbs_responsedata = { 0 };
myio_open_ibufstream(
&istream_tbs_responsedata,
tbs_responsedata_buffer, tbs_responsedata_len,
&errinfo);
#define SIGNATURE_SIZE
char signature_buffer[SIGNATURE_SIZE];
myio_obufstream_t ostream_signature = { 0 };
myio_open_obufstream(
&ostream_signature,
signature_buffer, sizeof(signature_buffer),
&errinfo);
gta_authenticate_data_detached(
h_ctx,
(gtaio_istream_t*)&istream_tbs_responsedata,
(gtaio_ostream_t*)&ostream_signature,
&errinfo);
myio_close_ibufstream(&istream_tbs_responsedata, &errinfo);
myio_close_obufstream(&ostream_signature, &errinfo);
gta_context_close(h_ctx, &errinfo);