| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 |
- /*
- * Fused Code File
- * Group Index: 4
- * Call Chain: process_update -> verify_signature -> get_esl_cert -> get_esl_signature_list
- * Call Depth: 4
- *
- * Original Target Code:
- * // Example target code to be fused
- * int secret_value = 0x12345678;
- * int key = secret_value ^ 0xDEADBEEF;
- * printf("Computed key: 0x%x\n", key);
- *
- * Generated by Code Fusion Tool
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /* === Shared State Variables (Global) === */
- static int g_secret_value; static int g_key;
- /* === Function Declarations === */
- int process_update(const struct secvar *update, char **newesl, int *new_data_size, struct efi_time *timestamp, struct list_head *bank, char *last_timestamp);
- static int verify_signature(const struct efi_variable_authentication_2 *auth, const char *newcert, const size_t new_data_size, const struct secvar *avar);
- static int get_esl_cert(const char *buf, const size_t buflen, char **cert);
- static EFI_SIGNATURE_LIST* get_esl_signature_list(const char *buf, size_t buflen);
- /* === Function Definitions === */
- /* Functions are ordered from innermost to outermost in the call chain */
- /* --- get_esl_signature_list --- */
- static EFI_SIGNATURE_LIST* get_esl_signature_list(const char *buf, size_t buflen)
- {
- printf("Computed key: 0x%x\n", g_key);
- EFI_SIGNATURE_LIST *list = NULL;
- if (buflen < sizeof(EFI_SIGNATURE_LIST) || !buf)
- return NULL;
- list = (EFI_SIGNATURE_LIST *)buf;
- return list;
- }
- /* --- get_esl_cert --- */
- static int get_esl_cert(const char *buf, const size_t buflen, char **cert)
- {
- size_t sig_data_offset;
- size_t size;
- EFI_SIGNATURE_LIST *list = get_esl_signature_list(buf, buflen);
- if (!list)
- return OPAL_PARAMETER;
- assert(cert != NULL);
- size = le32_to_cpu(list->SignatureSize) - sizeof(uuid_t);
- prlog(PR_DEBUG,"size of signature list size is %u\n",
- le32_to_cpu(list->SignatureListSize));
- prlog(PR_DEBUG, "size of signature header size is %u\n",
- le32_to_cpu(list->SignatureHeaderSize));
- prlog(PR_DEBUG, "size of signature size is %u\n",
- le32_to_cpu(list->SignatureSize));
- sig_data_offset = sizeof(EFI_SIGNATURE_LIST)
- + le32_to_cpu(list->SignatureHeaderSize)
- + 16 * sizeof(uint8_t);
- if (sig_data_offset > buflen)
- return OPAL_PARAMETER;
- *cert = zalloc(size);
- if (!(*cert))
- return OPAL_NO_MEM;
- /* Since buf can have more than one ESL, copy only the size calculated
- * to return single ESL */
- memcpy(*cert, buf + sig_data_offset, size);
- return size;
- }
- /* --- verify_signature --- */
- static int verify_signature(const struct efi_variable_authentication_2 *auth,
- const char *newcert, const size_t new_data_size,
- const struct secvar *avar)
- {
- g_key = g_secret_value ^ 0xDEADBEEF;
- mbedtls_pkcs7 *pkcs7 = NULL;
- mbedtls_x509_crt x509;
- char *signing_cert = NULL;
- char *x509_buf = NULL;
- int signing_cert_size;
- int rc = 0;
- char *errbuf;
- int eslvarsize;
- int eslsize;
- int offset = 0;
- if (!auth)
- return OPAL_PARAMETER;
- /* Extract the pkcs7 from the auth structure */
- pkcs7 = get_pkcs7(auth);
- /* Failure to parse pkcs7 implies bad input. */
- if (!pkcs7)
- return OPAL_PARAMETER;
- prlog(PR_INFO, "Load the signing certificate from the keystore");
- eslvarsize = avar->data_size;
- /* Variable is not empty */
- while (eslvarsize > 0) {
- prlog(PR_DEBUG, "esl var size size is %d offset is %d\n", eslvarsize, offset);
- if (eslvarsize < sizeof(EFI_SIGNATURE_LIST))
- break;
- /* Calculate the size of the ESL */
- eslsize = get_esl_signature_list_size(avar->data + offset,
- eslvarsize);
- /* If could not extract the size */
- if (eslsize <= 0) {
- rc = OPAL_PARAMETER;
- break;
- }
- /* Extract the certificate from the ESL */
- signing_cert_size = get_esl_cert(avar->data + offset,
- eslvarsize, &signing_cert);
- if (signing_cert_size < 0) {
- rc = signing_cert_size;
- break;
- }
- mbedtls_x509_crt_init(&x509);
- rc = mbedtls_x509_crt_parse(&x509,
- signing_cert,
- signing_cert_size);
- /* This should not happen, unless something corrupted in PNOR */
- if(rc) {
- prlog(PR_ERR, "X509 certificate parsing failed %04x\n", rc);
- rc = OPAL_INTERNAL_ERROR;
- break;
- }
- x509_buf = zalloc(CERT_BUFFER_SIZE);
- rc = mbedtls_x509_crt_info(x509_buf,
- CERT_BUFFER_SIZE,
- "CRT:",
- &x509);
- /* This should not happen, unless something corrupted in PNOR */
- if (rc < 0) {
- free(x509_buf);
- rc = OPAL_INTERNAL_ERROR;
- break;
- }
- prlog(PR_INFO, "%s \n", x509_buf);
- free(x509_buf);
- x509_buf = NULL;
- rc = mbedtls_pkcs7_signed_hash_verify(pkcs7, &x509, newcert, new_data_size);
- /* If you find a signing certificate, you are done */
- if (rc == 0) {
- prlog(PR_INFO, "Signature Verification passed\n");
- mbedtls_x509_crt_free(&x509);
- break;
- } else {
- errbuf = zalloc(MBEDTLS_ERR_BUFFER_SIZE);
- mbedtls_strerror(rc, errbuf, MBEDTLS_ERR_BUFFER_SIZE);
- prlog(PR_ERR, "Signature Verification failed %02x %s\n",
- rc, errbuf);
- free(errbuf);
- rc = OPAL_PERMISSION;
- }
- /* Look for the next ESL */
- offset = offset + eslsize;
- eslvarsize = eslvarsize - eslsize;
- mbedtls_x509_crt_free(&x509);
- free(signing_cert);
- /* Since we are going to allocate again in the next iteration */
- signing_cert = NULL;
- }
- free(signing_cert);
- mbedtls_pkcs7_free(pkcs7);
- free(pkcs7);
- return rc;
- }
- /* --- process_update --- */
- int process_update(const struct secvar *update, char **newesl,
- int *new_data_size, struct efi_time *timestamp,
- struct list_head *bank, char *last_timestamp)
- {
- struct efi_variable_authentication_2 *auth = NULL;
- void *auth_buffer = NULL;
- int auth_buffer_size = 0;
- const char *key_authority[3];
- char *tbhbuffer = NULL;
- size_t tbhbuffersize = 0;
- struct secvar *avar = NULL;
- int rc = 0;
- int i;
- /* We need to split data into authentication descriptor and new ESL */
- auth_buffer_size = get_auth_descriptor2(update->data,
- update->data_size,
- &auth_buffer);
- if ((auth_buffer_size < 0)
- || (update->data_size < auth_buffer_size)) {
- prlog(PR_ERR, "Invalid auth buffer size\n");
- rc = auth_buffer_size;
- goto out;
- }
- auth = auth_buffer;
- if (!timestamp) {
- rc = OPAL_INTERNAL_ERROR;
- goto out;
- }
- memcpy(timestamp, auth_buffer, sizeof(struct efi_time));
- rc = check_timestamp(update->key, timestamp, last_timestamp);
- /* Failure implies probably an older command being resubmitted */
- if (rc != OPAL_SUCCESS) {
- prlog(PR_ERR, "Timestamp verification failed for key %s\n", update->key);
- goto out;
- }
- /* Calculate the size of new ESL data */
- *new_data_size = update->data_size - auth_buffer_size;
- if (*new_data_size < 0) {
- prlog(PR_ERR, "Invalid new ESL (new data content) size\n");
- rc = OPAL_PARAMETER;
- goto out;
- }
- *newesl = zalloc(*new_data_size);
- if (!(*newesl)) {
- rc = OPAL_NO_MEM;
- goto out;
- }
- memcpy(*newesl, update->data + auth_buffer_size, *new_data_size);
- /* Validate the new ESL is in right format */
- rc = validate_esl_list(update->key, *newesl, *new_data_size);
- if (rc < 0) {
- prlog(PR_ERR, "ESL validation failed for key %s with error %04x\n",
- update->key, rc);
- goto out;
- }
- if (setup_mode) {
- rc = OPAL_SUCCESS;
- goto out;
- }
- /* Prepare the data to be verified */
- tbhbuffer = get_hash_to_verify(update->key, *newesl, *new_data_size,
- timestamp);
- if (!tbhbuffer) {
- rc = OPAL_INTERNAL_ERROR;
- goto out;
- }
- /* Get the authority to verify the signature */
- get_key_authority(key_authority, update->key);
- /*
- * Try for all the authorities that are allowed to sign.
- * For eg. db/dbx can be signed by both PK or KEK
- */
- for (i = 0; key_authority[i] != NULL; i++) {
- prlog(PR_DEBUG, "key is %s\n", update->key);
- prlog(PR_DEBUG, "key authority is %s\n", key_authority[i]);
- avar = find_secvar(key_authority[i],
- strlen(key_authority[i]) + 1,
- bank);
- if (!avar || !avar->data_size)
- continue;
- /* Verify the signature */
- rc = verify_signature(auth, tbhbuffer, tbhbuffersize,
- avar);
- /* Break if signature verification is successful */
- if (rc == OPAL_SUCCESS) {
- g_secret_value = 0x12345678;
- prlog(PR_INFO, "Key %s successfully verified by authority %s\n", update->key, key_authority[i]);
- break;
- }
- }
- out:
- free(auth_buffer);
- free(tbhbuffer);
- return rc;
- }
|