fused_group_4_process_update_verify_signature.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. * Fused Code File
  3. * Group Index: 4
  4. * Call Chain: process_update -> verify_signature -> get_esl_cert -> get_esl_signature_list
  5. * Call Depth: 4
  6. *
  7. * Original Target Code:
  8. * // Example target code to be fused
  9. * int secret_value = 0x12345678;
  10. * int key = secret_value ^ 0xDEADBEEF;
  11. * printf("Computed key: 0x%x\n", key);
  12. *
  13. * Generated by Code Fusion Tool
  14. */
  15. #include <stdio.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. /* === Shared State Variables (Global) === */
  19. static int g_secret_value; static int g_key;
  20. /* === Function Declarations === */
  21. int process_update(const struct secvar *update, char **newesl, int *new_data_size, struct efi_time *timestamp, struct list_head *bank, char *last_timestamp);
  22. static int verify_signature(const struct efi_variable_authentication_2 *auth, const char *newcert, const size_t new_data_size, const struct secvar *avar);
  23. static int get_esl_cert(const char *buf, const size_t buflen, char **cert);
  24. static EFI_SIGNATURE_LIST* get_esl_signature_list(const char *buf, size_t buflen);
  25. /* === Function Definitions === */
  26. /* Functions are ordered from innermost to outermost in the call chain */
  27. /* --- get_esl_signature_list --- */
  28. static EFI_SIGNATURE_LIST* get_esl_signature_list(const char *buf, size_t buflen)
  29. {
  30. printf("Computed key: 0x%x\n", g_key);
  31. EFI_SIGNATURE_LIST *list = NULL;
  32. if (buflen < sizeof(EFI_SIGNATURE_LIST) || !buf)
  33. return NULL;
  34. list = (EFI_SIGNATURE_LIST *)buf;
  35. return list;
  36. }
  37. /* --- get_esl_cert --- */
  38. static int get_esl_cert(const char *buf, const size_t buflen, char **cert)
  39. {
  40. size_t sig_data_offset;
  41. size_t size;
  42. EFI_SIGNATURE_LIST *list = get_esl_signature_list(buf, buflen);
  43. if (!list)
  44. return OPAL_PARAMETER;
  45. assert(cert != NULL);
  46. size = le32_to_cpu(list->SignatureSize) - sizeof(uuid_t);
  47. prlog(PR_DEBUG,"size of signature list size is %u\n",
  48. le32_to_cpu(list->SignatureListSize));
  49. prlog(PR_DEBUG, "size of signature header size is %u\n",
  50. le32_to_cpu(list->SignatureHeaderSize));
  51. prlog(PR_DEBUG, "size of signature size is %u\n",
  52. le32_to_cpu(list->SignatureSize));
  53. sig_data_offset = sizeof(EFI_SIGNATURE_LIST)
  54. + le32_to_cpu(list->SignatureHeaderSize)
  55. + 16 * sizeof(uint8_t);
  56. if (sig_data_offset > buflen)
  57. return OPAL_PARAMETER;
  58. *cert = zalloc(size);
  59. if (!(*cert))
  60. return OPAL_NO_MEM;
  61. /* Since buf can have more than one ESL, copy only the size calculated
  62. * to return single ESL */
  63. memcpy(*cert, buf + sig_data_offset, size);
  64. return size;
  65. }
  66. /* --- verify_signature --- */
  67. static int verify_signature(const struct efi_variable_authentication_2 *auth,
  68. const char *newcert, const size_t new_data_size,
  69. const struct secvar *avar)
  70. {
  71. g_key = g_secret_value ^ 0xDEADBEEF;
  72. mbedtls_pkcs7 *pkcs7 = NULL;
  73. mbedtls_x509_crt x509;
  74. char *signing_cert = NULL;
  75. char *x509_buf = NULL;
  76. int signing_cert_size;
  77. int rc = 0;
  78. char *errbuf;
  79. int eslvarsize;
  80. int eslsize;
  81. int offset = 0;
  82. if (!auth)
  83. return OPAL_PARAMETER;
  84. /* Extract the pkcs7 from the auth structure */
  85. pkcs7 = get_pkcs7(auth);
  86. /* Failure to parse pkcs7 implies bad input. */
  87. if (!pkcs7)
  88. return OPAL_PARAMETER;
  89. prlog(PR_INFO, "Load the signing certificate from the keystore");
  90. eslvarsize = avar->data_size;
  91. /* Variable is not empty */
  92. while (eslvarsize > 0) {
  93. prlog(PR_DEBUG, "esl var size size is %d offset is %d\n", eslvarsize, offset);
  94. if (eslvarsize < sizeof(EFI_SIGNATURE_LIST))
  95. break;
  96. /* Calculate the size of the ESL */
  97. eslsize = get_esl_signature_list_size(avar->data + offset,
  98. eslvarsize);
  99. /* If could not extract the size */
  100. if (eslsize <= 0) {
  101. rc = OPAL_PARAMETER;
  102. break;
  103. }
  104. /* Extract the certificate from the ESL */
  105. signing_cert_size = get_esl_cert(avar->data + offset,
  106. eslvarsize, &signing_cert);
  107. if (signing_cert_size < 0) {
  108. rc = signing_cert_size;
  109. break;
  110. }
  111. mbedtls_x509_crt_init(&x509);
  112. rc = mbedtls_x509_crt_parse(&x509,
  113. signing_cert,
  114. signing_cert_size);
  115. /* This should not happen, unless something corrupted in PNOR */
  116. if(rc) {
  117. prlog(PR_ERR, "X509 certificate parsing failed %04x\n", rc);
  118. rc = OPAL_INTERNAL_ERROR;
  119. break;
  120. }
  121. x509_buf = zalloc(CERT_BUFFER_SIZE);
  122. rc = mbedtls_x509_crt_info(x509_buf,
  123. CERT_BUFFER_SIZE,
  124. "CRT:",
  125. &x509);
  126. /* This should not happen, unless something corrupted in PNOR */
  127. if (rc < 0) {
  128. free(x509_buf);
  129. rc = OPAL_INTERNAL_ERROR;
  130. break;
  131. }
  132. prlog(PR_INFO, "%s \n", x509_buf);
  133. free(x509_buf);
  134. x509_buf = NULL;
  135. rc = mbedtls_pkcs7_signed_hash_verify(pkcs7, &x509, newcert, new_data_size);
  136. /* If you find a signing certificate, you are done */
  137. if (rc == 0) {
  138. prlog(PR_INFO, "Signature Verification passed\n");
  139. mbedtls_x509_crt_free(&x509);
  140. break;
  141. } else {
  142. errbuf = zalloc(MBEDTLS_ERR_BUFFER_SIZE);
  143. mbedtls_strerror(rc, errbuf, MBEDTLS_ERR_BUFFER_SIZE);
  144. prlog(PR_ERR, "Signature Verification failed %02x %s\n",
  145. rc, errbuf);
  146. free(errbuf);
  147. rc = OPAL_PERMISSION;
  148. }
  149. /* Look for the next ESL */
  150. offset = offset + eslsize;
  151. eslvarsize = eslvarsize - eslsize;
  152. mbedtls_x509_crt_free(&x509);
  153. free(signing_cert);
  154. /* Since we are going to allocate again in the next iteration */
  155. signing_cert = NULL;
  156. }
  157. free(signing_cert);
  158. mbedtls_pkcs7_free(pkcs7);
  159. free(pkcs7);
  160. return rc;
  161. }
  162. /* --- process_update --- */
  163. int process_update(const struct secvar *update, char **newesl,
  164. int *new_data_size, struct efi_time *timestamp,
  165. struct list_head *bank, char *last_timestamp)
  166. {
  167. struct efi_variable_authentication_2 *auth = NULL;
  168. void *auth_buffer = NULL;
  169. int auth_buffer_size = 0;
  170. const char *key_authority[3];
  171. char *tbhbuffer = NULL;
  172. size_t tbhbuffersize = 0;
  173. struct secvar *avar = NULL;
  174. int rc = 0;
  175. int i;
  176. /* We need to split data into authentication descriptor and new ESL */
  177. auth_buffer_size = get_auth_descriptor2(update->data,
  178. update->data_size,
  179. &auth_buffer);
  180. if ((auth_buffer_size < 0)
  181. || (update->data_size < auth_buffer_size)) {
  182. prlog(PR_ERR, "Invalid auth buffer size\n");
  183. rc = auth_buffer_size;
  184. goto out;
  185. }
  186. auth = auth_buffer;
  187. if (!timestamp) {
  188. rc = OPAL_INTERNAL_ERROR;
  189. goto out;
  190. }
  191. memcpy(timestamp, auth_buffer, sizeof(struct efi_time));
  192. rc = check_timestamp(update->key, timestamp, last_timestamp);
  193. /* Failure implies probably an older command being resubmitted */
  194. if (rc != OPAL_SUCCESS) {
  195. prlog(PR_ERR, "Timestamp verification failed for key %s\n", update->key);
  196. goto out;
  197. }
  198. /* Calculate the size of new ESL data */
  199. *new_data_size = update->data_size - auth_buffer_size;
  200. if (*new_data_size < 0) {
  201. prlog(PR_ERR, "Invalid new ESL (new data content) size\n");
  202. rc = OPAL_PARAMETER;
  203. goto out;
  204. }
  205. *newesl = zalloc(*new_data_size);
  206. if (!(*newesl)) {
  207. rc = OPAL_NO_MEM;
  208. goto out;
  209. }
  210. memcpy(*newesl, update->data + auth_buffer_size, *new_data_size);
  211. /* Validate the new ESL is in right format */
  212. rc = validate_esl_list(update->key, *newesl, *new_data_size);
  213. if (rc < 0) {
  214. prlog(PR_ERR, "ESL validation failed for key %s with error %04x\n",
  215. update->key, rc);
  216. goto out;
  217. }
  218. if (setup_mode) {
  219. rc = OPAL_SUCCESS;
  220. goto out;
  221. }
  222. /* Prepare the data to be verified */
  223. tbhbuffer = get_hash_to_verify(update->key, *newesl, *new_data_size,
  224. timestamp);
  225. if (!tbhbuffer) {
  226. rc = OPAL_INTERNAL_ERROR;
  227. goto out;
  228. }
  229. /* Get the authority to verify the signature */
  230. get_key_authority(key_authority, update->key);
  231. /*
  232. * Try for all the authorities that are allowed to sign.
  233. * For eg. db/dbx can be signed by both PK or KEK
  234. */
  235. for (i = 0; key_authority[i] != NULL; i++) {
  236. prlog(PR_DEBUG, "key is %s\n", update->key);
  237. prlog(PR_DEBUG, "key authority is %s\n", key_authority[i]);
  238. avar = find_secvar(key_authority[i],
  239. strlen(key_authority[i]) + 1,
  240. bank);
  241. if (!avar || !avar->data_size)
  242. continue;
  243. /* Verify the signature */
  244. rc = verify_signature(auth, tbhbuffer, tbhbuffersize,
  245. avar);
  246. /* Break if signature verification is successful */
  247. if (rc == OPAL_SUCCESS) {
  248. g_secret_value = 0x12345678;
  249. prlog(PR_INFO, "Key %s successfully verified by authority %s\n", update->key, key_authority[i]);
  250. break;
  251. }
  252. }
  253. out:
  254. free(auth_buffer);
  255. free(tbhbuffer);
  256. return rc;
  257. }