The example below enumerates all personalities with application “IDevID”. This can be useful to select personalities usable for onboarding (cf. 5.2.2, Figure 9).

  1. gta_instance_handle_t h_inst;
  2. gta_context_handle_t h_ctx = GTA_HANDLE_INVALID;
  3. gta_errinfo_t errinfo;
  4. bool b_loop_pers = true;
  5. gta_enum_handle_t h_enum_pers = GTA_HANDLE_ENUM_FIRST;
  6. while (b_loop_pers) {
  7. char pers_name[STR_LEN_MAX];
  8. myio_obufstream_t ostream_pers_name = { 0 };
  9. myio_open_obufstream(&ostream_pers_name, pers_name,
  10. sizeof(pers_name), &errinfo);
  11. if (gta_personality_enumerate_application(h_inst,
  12. "IDevID", h_enum_pers, GTA_PERSONALITY_ENUM_ALL,
  13. (gtaio_ostream_t *)&o_pers_name, &errinfo)) {
  14. /*
  15. * do something with personality pers_name
  16. */
  17. }
  18. else {
  19. b_loop_pers = false;
  20. }
  21. myio_close_obufstream(&ostream_pers_name, &errinfo);
  22. }
  23. }

The example below enumerates all personalities and checks for the attribute org.opcfoundation.product_instance_uri

  1. bool b_loop = true;
  2. char identifier_type_buffer[200];
  3. char identifier_value_buffer[200];
  4. myio_obufstream_t ostream_identifier_type = { 0 };
  5. myio_obufstream_t ostream_identifier_value = { 0 };
  6. gta_enum_handle_t h_enum = GTA_HANDLE_ENUM_FIRST;
  7. gta_context_handle_t h_ctx = GTA_HANDLE_INVALID;
  8. bool exit_loops = false;
  9. char selected_personality[100];
  10. /* enumerate all identifiers */
  11. while (b_loop && !exit_loops) {
  12. myio_open_obufstream(&ostream_identifier_type,
  13. identifier_type_buffer,
  14. sizeof(identifier_type_buffer),
  15. &errinfo);
  16. myio_open_obufstream(&ostream_identifier_value,
  17. identifier_value_buffer,
  18. sizeof(identifier_value_buffer),
  19. &errinfo);
  20. b_ret = gta_identifier_enumerate(
  21. h_inst,
  22. &h_enum,
  23. (gtaio_ostream_t *)&ostream_identifier_type,
  24. (gtaio_ostream_t *)&ostream_identifier_value,
  25. &errinfo);
  26. myio_close_obufstream(&ostream_identifier_type, &errinfo);
  27. myio_close_obufstream(&ostream_identifier_value, &errinfo);
  28. if (true == b_ret) {
  29. bool b_inner_loop = true;
  30. char personality_name_buffer[200];
  31. myio_obufstream_t ostream_personality_name = { 0 };
  32. gta_enum_handle_t h_enum_inner_loop = GTA_HANDLE_ENUM_FIRST;
  33. /* enumerate all personalities belonging to identifier */
  34. while (b_inner_loop && !exit_loops) {
  35. myio_open_obufstream(&ostream_personality_name,
  36. personality_name_buffer,
  37. sizeof(personality_name_buffer),
  38. &errinfo);
  39. b_ret = gta_personality_enumerate(
  40. h_inst,
  41. identifier_value_buffer,
  42. &h_enum_inner_loop,
  43. GTA_PERSONALITY_ENUM_ALL,
  44. (gtaio_ostream_t *)&ostream_personality_name,
  45. &errinfo);
  46. myio_close_obufstream(&ostream_personality_name, &errinfo);
  47. if (true == b_ret) {
  48. bool b_innermost_loop = true;
  49. char attribute_type_buffer[200];
  50. char attribute_value_buffer[200];
  51. myio_obufstream_t ostream_attribute_type = { 0 };
  52. myio_obufstream_t ostream_attribute_value = { 0 };
  53. gta_enum_handle_t h_enum_innermost_loop
  54. = GTA_HANDLE_ENUM_FIRST;
  55. /* enumerate all attributes belonging to personality */
  56. while (b_innermost_loop && !exit_loops) {
  57. myio_open_obufstream(
  58. &ostream_attribute_type,
  59. attribute_type_buffer,
  60. sizeof(attribute_type_buffer),
  61. &errinfo);
  62. myio_open_obufstream(
  63. &ostream_attribute_value,
  64. attribute_value_buffer,
  65. sizeof(attribute_value_buffer),
  66. &errinfo);
  67. b_ret = gta_personality_attributes_enumerate(
  68. h_inst,
  69. personality_name_buffer,
  70. &h_enum_innermost_loop,
  71. (gtaio_ostream_t *)&ostream_attribute_type,
  72. (gtaio_ostream_t *)&ostream_attribute_value,
  73. &errinfo);
  74. myio_close_obufstream(&ostream_attribute_type,
  75. &errinfo);
  76. myio_close_obufstream(&ostream_attribute_value,
  77. &errinfo);
  78. if (true == b_ret) {
  79. if (0 == strcmp(
  80. "org.opcfoundation.product_instance_uri",
  81. attribute_type_buffer)) {
  82. exit_loops = true;
  83. strcpy(selected_personality,
  84. personality_name_buffer);
  85. }
  86. }
  87. else {
  88. b_innermost_loop = false;
  89. }
  90. }
  91. }
  92. else {
  93. errinfo = 0;
  94. b_inner_loop = false;
  95. }
  96. }
  97. }
  98. else {
  99. errinfo = 0;
  100. b_loop = false;
  101. }
  102. }
  103. /*
  104. * do something with selected personality
  105. */

The example below searches all attributes of a personality given by its name pers_name for an X.509 DeviceIdentity certificate.

  1. bool b_loop_attr = true;
  2. gta_enum_handle_t h_enum_attr = GTA_HANDLE_ENUM_FIRST;
  3. while (b_loop_attr) {
  4. char attr_name[STR_LEN_MAX];
  5. char attr_type[STR_LEN_MAX];
  6. myio_obufstream_t ostream_attr_name = { 0 };
  7. myio_obufstream_t ostream_attr_type = { 0 };
  8. myio_open_obufstream(&ostream_attr_name, attr_name,
  9. sizeof(attr_name), &errinfo);
  10. myio_open_obufstream(&ostream_attr_type, attr_type,
  11. sizeof(attr_type), &errinfo);
  12. if (gta_personality_attributes_enumerate(h_inst,
  13. pers_name,
  14. h_enum_attr,
  15. (gtaio_ostream_t *)&ostream_attr_name,
  16. (gtaio_ostream_t *)&ostream_attr_type,
  17. &errinfo)) {
  18. /* Get the attribute holding the
  19. DeviceIdentity Certificate */
  20. if (0 == strncmp(attr_type,
  21. "ch.iec.30168.trustlist.certificate.self.x509",
  22. STR_LEN_MAX)) {
  23. h_ctx = gta_context_open(h_inst,
  24. pers_name,
  25. "org.opcfoundation.ECC-nistP256",
  26. &errinfo);
  27. /* get application certificate */
  28. char devid_cert[CERT_SIZE_MAX];
  29. myio_obufstream_t ostream_devid_cert = { 0 };
  30. myio_open_obufstream(&ostream_devid_cert,
  31. devid_cert, sizeof(devid_cert), &errinfo);
  32. gta_personality_get_attribute(h_ctx,
  33. attr_name, (gtaio_ostream_t *)&ostream_devid_cert,
  34. &errinfo);
  35. /* ... make use of this DeviceIdentity Cerficate
  36. (e.g., add it to a list) ... */
  37. gta_context_close(h_ctx, &errinfo);
  38. }
  39. }
  40. else {
  41. b_loop_attr = false;
  42. }
  43. myio_close_obufstream(&ostream_attr_name, &errinfo);
  44. myio_close_obufstream(&ostream_attr_type, &errinfo);
  45. }

The 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.

  1. gta_errinfo_t errinfo = 0;
  2. char identifier_value[]
  3. = "urn:manufacturer.com:2024-10:myproduct:SN51235";
  4. char personality_name[]
  5. = "urn:manufacturer.com:2024-10:myproduct:SN51235?"
  6. "cg=DefaultApplicationGroup&ct=EccNistP256&ix=1";
  7. char identity_profile[]
  8. = "org.opcfoundation.ECC-nistP256";
  9. char application[] = "DCA Identity";
  10. char trustlist_personality_name[]
  11. = "urn:manufacturer.com:2024-10:myproduct:SN51235?"
  12. "cg=DefaultApplicationGroup";
  13. char trustlist_application[] = "DCA TrustList";
  14. char trustlist_profile[]
  15. = "ch.iec.30168.basic.local_data_integrity_only";
  16. /* Assign identifier */
  17. gta_identifier_assign(
  18. h_inst,
  19. "org.opcfoundation.application_instance_uri",
  20. identifier_value,
  21. &errinfo);
  22. /* Create DCA Identity Personality */
  23. gta_access_policy_handle_t h_auth_use = GTA_HANDLE_INVALID;
  24. h_auth_use = gta_access_policy_simple(
  25. h_inst,
  26. GTA_ACCESS_DESCRIPTOR_TYPE_INITIAL,
  27. &errinfo);
  28. gta_access_policy_handle_t h_auth_use = GTA_HANDLE_INVALID;
  29. h_auth_admin = gta_access_policy_simple(
  30. h_inst,
  31. GTA_ACCESS_DESCRIPTOR_TYPE_INITIAL,
  32. &errinfo);
  33. struct gta_protection_properties_t protection_props = {0};
  34. gta_personality_create(
  35. h_inst,
  36. identifier_value,
  37. personality_name,
  38. application,
  39. identity_profile,
  40. h_auth_use,
  41. h_auth_admin,
  42. protection_props,
  43. &errinfo);
  44. /* Generate CSR */
  45. gta_context_handle_t h_ctx = GTA_HANDLE_INVALID;
  46. h_ctx = gta_context_open(
  47. h_inst,
  48. personality_name,
  49. "com.github.generic-trust-anchor-api.basic.enroll",
  50. &errinfo);
  51. /* Set context attribute org.opcfoundation.csr.subject */
  52. const char subject_der[] = {…};
  53. size_t subject_der_len = …;
  54. myio_ibufstream_t istream_subject = { 0 };
  55. myio_open_ibufstream(
  56. &istream_subject,
  57. subject_der, subject_der_len,
  58. &errinfo);
  59. gta_context_set_attribute(
  60. h_ctx,
  61. "org.opcfoundation.csr.subject",
  62. (gtaio_istream_t*)&istream_subject,
  63. &errinfo);
  64. myio_close_ibufstream(&istream_subject, &errinfo);
  65. /* Set context attribute org.opcfoundation.csr.subjectAltName */
  66. const char subject_alt_name_der[] = {…};
  67. size_t subject_alt_name_der_len = …;
  68. myio_ibufstream_t istream_subject_alt_name = { 0 };
  69. myio_open_ibufstream(
  70. &istream_subject_alt_name,
  71. subject_alt_name_der, subject_alt_name_der_len,
  72. &errinfo);
  73. gta_context_set_attribute(
  74. h_ctx,
  75. "org.opcfoundation.csr.subjectAltName",
  76. (gtaio_istream_t*)&istream_subject_alt_name,
  77. &errinfo);
  78. myio_close_ibufstream(&istream_subject_alt_name, &errinfo);
  79. char csr_buffer[CSR_SIZE];
  80. myio_obufstream_t ostream_csr = { 0 };
  81. myio_open_obufstream(
  82. &ostream_csr,
  83. csr_buffer, sizeof(csr_buffer),
  84. &errinfo);
  85. gta_personality_enroll(
  86. h_ctx,
  87. (gtaio_ostream_t*)&ostream_csr,
  88. &errinfo);
  89. myio_close_obufstream(&ostream_csr, &errinfo);
  90. /* Send CSR and receive certificate */
  91. char cert_buffer[] = {…};
  92. size_t cert_len = …;
  93. /* Store DCA certificate (optional) */
  94. myio_ibufstream_t istream_cert = { 0 };
  95. myio_open_ibufstream(
  96. &istream_cert,
  97. cert_buffer, cert_len,
  98. &errinfo);
  99. gta_personality_add_attribute(
  100. h_ctx,
  101. "ch.iec.30168.trustlist.certificate.self.x509",
  102. "DCA certificate",
  103. (gtaio_istream_t*)&istream_cert,
  104. &errinfo);
  105. myio_close_ibufstream(&istream_cert, &errinfo);
  106. gta_context_close(h_ctx, &errinfo);
  107. /* Receive TrustList */
  108. char trustlist_buffer[] = {…};
  109. size_t trustlist_len = …;
  110. /* Create DCA TrustList Personality */
  111. gta_personality_create(
  112. h_inst,
  113. identifier_value,
  114. trustlist_personality_name,
  115. trustlist_application,
  116. trustlist_profile,
  117. h_auth_use,
  118. h_auth_admin,
  119. protection_props,
  120. &errinfo);
  121. /* Protect DCA TrustList objects */
  122. gta_context_handle_t h_ctx_seal = GTA_HANDLE_INVALID;
  123. h_ctx_seal = gta_context_open(
  124. h_inst,
  125. trustlist_personality_name,
  126. trustlist_profile,
  127. &errinfo);
  128. myio_ibufstream_t istream_trustlist = { 0 };
  129. myio_open_ibufstream(
  130. &istream_trustlist,
  131. trustlist_buffer, trustlist_len,
  132. &errinfo);
  133. #define INTEGRITY_PROTECTION_SEAL_LENGTH 32
  134. char seal_buffer[INTEGRITY_PROTECTION_SEAL_LENGTH];
  135. myio_obufstream_t ostream_seal = { 0 };
  136. myio_open_obufstream(
  137. &ostream_seal,
  138. seal_buffer, sizeof(seal_buffer),
  139. &errinfo);
  140. gta_authenticate_data_detached(
  141. h_ctx_seal,
  142. (gtaio_istream_t*)&istream_trustlist,
  143. (gtaio_ostream_t*)&ostream_seal,
  144. &errinfo);
  145. myio_close_ibufstream(&istream_trustlist, &errinfo);
  146. myio_close_obufstream(&ostream_seal, &errinfo);
  147. gta_context_close(h_ctx_seal, &errinfo);

The 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=1

  1. gta_errinfo_t errinfo = 0;
  2. char personality_name[]
  3. = "urn:manufacturer.com:2024-10:myproduct:myserver_appid?"
  4. "cg=DefaultApplicationGroup&ct=Rsa2048&ix=1";
  5. char profile[]
  6. = "org.opcfoundation.Aes256-Sha256-RsaPss";
  7. char certificate_name = "my_server";
  8. char trustlist_personality_name[]
  9. = "urn:manufacturer.com:2024-10:myproduct:myserver_appid?"
  10. "cg=DefaultApplicationGroup;
  11. char trustlist_profile[]
  12. = "ch.iec.30168.basic.local_data_integrity_only";
  13. gta_context_handle_t h_ctx = GTA_HANDLE_INVALID;
  14. h_ctx = gta_context_open(
  15. h_inst,
  16. personality_name,
  17. profile,
  18. &errinfo);
  19. /* Get server certificate from personality attribute (optional) */
  20. char cert_buffer[CERT_SIZE];
  21. myio_obufstream_t ostream_cert = { 0 };
  22. gta_personality_get_attribute(
  23. h_ctx,
  24. certificate_name,
  25. (gtaio_ostream_t*)&ostream_cert,
  26. &errinfo);
  27. myio_close_obufstream(&ostream_cert, &errinfo);
  28. /* Prepare OpenSecureChannel Response */
  29. gta_context_handle_t h_ctx_seal = GTA_HANDLE_INVALID;
  30. h_ctx_seal = gta_context_open(
  31. h_inst,
  32. trustlist_personality_name,
  33. trustlist_profile,
  34. &errinfo);
  35. char trustlist_buffer[] = {…};
  36. size_t trustlist_len = …;
  37. myio_ibufstream_t istream_trustlist = { 0 };
  38. myio_open_ibufstream(
  39. &istream_trustlist,
  40. trustlist_buffer, trustlist_len,
  41. &errinfo);
  42. char seal_buffer[] = {…};
  43. size_t seal_len = …;
  44. myio_ibufstream_t istream_seal = { 0 };
  45. myio_open_ibufstream(
  46. &istream_seal,
  47. seal_buffer, seal_len,
  48. &errinfo);
  49. if (!gta_verify_data_detached(
  50. h_ctx_seal,
  51. (gtaio_istream_t*)&istream_trustlist,
  52. (gtaio_istream_t*)&istream_seal,
  53. &errinfo)) {
  54. /* fail – TrustList has been tampered with */
  55. }
  56. myio_close_ibufstream(&istream_trustlist, &errinfo);
  57. myio_close_ibufstream(&istream_seal, &errinfo);
  58. gta_context_close(h_ctx_seal, &errinfo);
  59. char encrypted_requestdata_buffer[] = {…};
  60. size_t encrypted_requestdata_len = …;
  61. myio_ibufstream_t istream_encrypted_requestdata = { 0 };
  62. myio_open_ibufstream(
  63. &istream_encrypted_requestdata,
  64. encrypted_requestdata_buffer, encrypted_requestdata_len,
  65. &errinfo);
  66. #define REQUESTDATA_SIZE
  67. char decrypted_requestdata_buffer[REQUESTDATA_SIZE];
  68. myio_obufstream_t ostream_decrypted_requestdata = { 0 };
  69. myio_open_obufstream(
  70. &ostream_decrypted_requestdata,
  71. decrypted_requestdata_buffer, sizeof(decrypted_requestdata_buffer),
  72. &errinfo);
  73. gta_unseal_data(
  74. h_ctx,
  75. (gtaio_istream_t*)&istream_encrypted_requestdata,
  76. (gtaio_ostream_t*)&ostream_decrypted_requestdata,
  77. &errinfo);
  78. myio_close_ibufstream(&istream_encrypted_requestdata, &errinfo);
  79. myio_close_obufstream(&ostream_decrypted_requestdata, &errinfo);
  80. char tbs_responsedata_buffer[] = {…};
  81. size_t tbs_responsedata_len = …;
  82. myio_ibufstream_t istream_tbs_responsedata = { 0 };
  83. myio_open_ibufstream(
  84. &istream_tbs_responsedata,
  85. tbs_responsedata_buffer, tbs_responsedata_len,
  86. &errinfo);
  87. #define SIGNATURE_SIZE
  88. char signature_buffer[SIGNATURE_SIZE];
  89. myio_obufstream_t ostream_signature = { 0 };
  90. myio_open_obufstream(
  91. &ostream_signature,
  92. signature_buffer, sizeof(signature_buffer),
  93. &errinfo);
  94. gta_authenticate_data_detached(
  95. h_ctx,
  96. (gtaio_istream_t*)&istream_tbs_responsedata,
  97. (gtaio_ostream_t*)&ostream_signature,
  98. &errinfo);
  99. myio_close_ibufstream(&istream_tbs_responsedata, &errinfo);
  100. myio_close_obufstream(&ostream_signature, &errinfo);
  101. gta_context_close(h_ctx, &errinfo);