LCOV - code coverage report
Current view: top level - libstb/secvar/backend - edk2-compat-process.c (source / functions) Hit Total Coverage
Test: skiboot.info Lines: 355 418 84.9 %
Date: 2024-09-10 18:37:41 Functions: 20 20 100.0 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
       2                 :            : /* Copyright 2020 IBM Corp. */
       3                 :            : #ifndef pr_fmt
       4                 :            : #define pr_fmt(fmt) "EDK2_COMPAT: " fmt
       5                 :            : #endif
       6                 :            : 
       7                 :            : #include <opal.h>
       8                 :            : #include <string.h>
       9                 :            : #include <time.h>
      10                 :            : #include <unistd.h>
      11                 :            : #include <stdint.h>
      12                 :            : #include <ccan/endian/endian.h>
      13                 :            : #include <mbedtls/error.h>
      14                 :            : #include <mbedtls/oid.h>
      15                 :            : #include <device.h>
      16                 :            : #include <assert.h>
      17                 :            : #include "libstb/crypto/pkcs7/pkcs7.h"
      18                 :            : #include "edk2.h"
      19                 :            : #include "../secvar.h"
      20                 :            : #include "edk2-compat-process.h"
      21                 :            : 
      22                 :            : bool setup_mode;
      23                 :            : 
      24                 :         12 : int update_variable_in_bank(struct secvar *update_var, const char *data,
      25                 :            :                             const uint64_t dsize, struct list_head *bank)
      26                 :            : {
      27                 :            :         struct secvar *var;
      28                 :            : 
      29                 :         12 :         var = find_secvar(update_var->key, update_var->key_len, bank);
      30                 :         12 :         if (!var)
      31                 :          0 :                 return OPAL_EMPTY;
      32                 :            : 
      33                 :            :         /* Reallocate the data memory, if there is change in data size */
      34                 :         12 :         if (var->data_size < dsize)
      35                 :          9 :                 if (realloc_secvar(var, dsize))
      36                 :          0 :                         return OPAL_NO_MEM;
      37                 :            : 
      38                 :         12 :         if (dsize && data)
      39                 :         10 :                 memcpy(var->data, data, dsize);
      40                 :         12 :         var->data_size = dsize;
      41                 :            : 
      42                 :            :         /* Clear the volatile bit only if updated with positive data size */
      43                 :         12 :         if (dsize)
      44                 :         10 :                 var->flags &= ~SECVAR_FLAG_VOLATILE;
      45                 :            :         else
      46                 :          2 :                 var->flags |= SECVAR_FLAG_VOLATILE;
      47                 :            : 
      48                 :         12 :         if (key_equals(update_var->key, "PK")
      49                 :          7 :             || key_equals(update_var->key, "HWKH")
      50                 :          7 :             || key_equals(update_var->key, "TS"))
      51                 :          5 :                 var->flags |= SECVAR_FLAG_PROTECTED;
      52                 :            : 
      53                 :         12 :         return 0;
      54                 :            : }
      55                 :            : 
      56                 :            : /* Expand char to wide character size */
      57                 :         14 : static char *char_to_wchar(const char *key, const size_t keylen)
      58                 :            : {
      59                 :            :         int i;
      60                 :            :         char *str;
      61                 :            : 
      62                 :         14 :         str = zalloc(keylen * 2);
      63                 :         14 :         if (!str)
      64                 :          0 :                 return NULL;
      65                 :            : 
      66                 :         46 :         for (i = 0; i < keylen*2; key++) {
      67                 :         32 :                 str[i++] = *key;
      68                 :         32 :                 str[i++] = '\0';
      69                 :            :         }
      70                 :            : 
      71                 :         14 :         return str;
      72                 :            : }
      73                 :            : 
      74                 :            : /* Returns the authority that can sign the given key update */
      75                 :         14 : static void get_key_authority(const char *ret[3], const char *key)
      76                 :            : {
      77                 :         14 :         int i = 0;
      78                 :            : 
      79                 :         14 :         if (key_equals(key, "PK")) {
      80                 :          2 :                 ret[i++] = "PK";
      81                 :         12 :         } else if (key_equals(key, "KEK")) {
      82                 :          3 :                 ret[i++] = "PK";
      83                 :          9 :         } else if (key_equals(key, "db") || key_equals(key, "dbx")) {
      84                 :          9 :                 ret[i++] = "KEK";
      85                 :          9 :                 ret[i++] = "PK";
      86                 :            :         }
      87                 :            : 
      88                 :         14 :         ret[i] = NULL;
      89                 :         14 : }
      90                 :            : 
      91                 :         92 : static EFI_SIGNATURE_LIST* get_esl_signature_list(const char *buf, size_t buflen)
      92                 :            : {
      93                 :         92 :         EFI_SIGNATURE_LIST *list = NULL;
      94                 :            : 
      95                 :         92 :         if (buflen < sizeof(EFI_SIGNATURE_LIST) || !buf)
      96                 :          0 :                 return NULL;
      97                 :            : 
      98                 :         92 :         list = (EFI_SIGNATURE_LIST *)buf;
      99                 :            : 
     100                 :         92 :         return list;
     101                 :            : }
     102                 :            : 
     103                 :            : /* Returns the size of the complete ESL. */
     104                 :         16 : static int32_t get_esl_signature_list_size(const char *buf, const size_t buflen)
     105                 :            : {
     106                 :         16 :         EFI_SIGNATURE_LIST *list = get_esl_signature_list(buf, buflen);
     107                 :            : 
     108                 :         16 :         if (!list)
     109                 :          0 :                 return OPAL_PARAMETER;
     110                 :            : 
     111                 :         16 :         return le32_to_cpu(list->SignatureListSize);
     112                 :            : }
     113                 :            : 
     114                 :            : /* 
     115                 :            :  * Copies the certificate from the ESL into cert buffer and returns the size
     116                 :            :  * of the certificate
     117                 :            :  */
     118                 :         46 : static int get_esl_cert(const char *buf, const size_t buflen, char **cert)
     119                 :            : {
     120                 :            :         size_t sig_data_offset;
     121                 :            :         size_t size;
     122                 :         46 :         EFI_SIGNATURE_LIST *list = get_esl_signature_list(buf, buflen);
     123                 :            : 
     124                 :         46 :         if (!list)
     125                 :          0 :                 return OPAL_PARAMETER;
     126                 :            : 
     127                 :         46 :         assert(cert != NULL);
     128                 :            : 
     129                 :         46 :         if (le32_to_cpu(list->SignatureSize) <= sizeof(uuid_t))
     130                 :          1 :                 return OPAL_PARAMETER;
     131                 :            : 
     132                 :         45 :         size = le32_to_cpu(list->SignatureSize) - sizeof(uuid_t);
     133                 :            : 
     134                 :         45 :         prlog(PR_DEBUG,"size of signature list size is %u\n",
     135                 :            :                         le32_to_cpu(list->SignatureListSize));
     136                 :         45 :         prlog(PR_DEBUG, "size of signature header size is %u\n",
     137                 :            :                         le32_to_cpu(list->SignatureHeaderSize));
     138                 :         45 :         prlog(PR_DEBUG, "size of signature size is %u\n",
     139                 :            :                         le32_to_cpu(list->SignatureSize));
     140                 :            : 
     141                 :         45 :         sig_data_offset = sizeof(EFI_SIGNATURE_LIST)
     142                 :         45 :                           + le32_to_cpu(list->SignatureHeaderSize)
     143                 :            :                           + 16 * sizeof(uint8_t);
     144                 :            : 
     145                 :            :         /* Ensure this ESL does not overflow the bounds of the buffer */
     146                 :         45 :         if (sig_data_offset + size > buflen) {
     147                 :          2 :                 prlog(PR_ERR, "Number of bytes of ESL data is less than size specified\n");
     148                 :          2 :                 return OPAL_PARAMETER;
     149                 :            :         }
     150                 :            : 
     151                 :         43 :         *cert = zalloc(size);
     152                 :         43 :         if (!(*cert))
     153                 :          0 :                 return OPAL_NO_MEM;
     154                 :            : 
     155                 :            :         /* Since buf can have more than one ESL, copy only the size calculated
     156                 :            :          * to return single ESL */
     157                 :         43 :         memcpy(*cert, buf + sig_data_offset, size);
     158                 :            : 
     159                 :         43 :         return size;
     160                 :            : }
     161                 :            : 
     162                 :            : /* 
     163                 :            :  * Extracts size of the PKCS7 signed data embedded in the
     164                 :            :  * struct Authentication 2 Descriptor Header.
     165                 :            :  */
     166                 :         50 : static size_t get_pkcs7_len(const struct efi_variable_authentication_2 *auth)
     167                 :            : {
     168                 :            :         uint32_t dw_length;
     169                 :            :         size_t size;
     170                 :            : 
     171                 :         50 :         assert(auth != NULL);
     172                 :            : 
     173                 :         50 :         dw_length = le32_to_cpu(auth->auth_info.hdr.dw_length);
     174                 :         50 :         size = dw_length - (sizeof(auth->auth_info.hdr.dw_length)
     175                 :            :                         + sizeof(auth->auth_info.hdr.w_revision)
     176                 :            :                         + sizeof(auth->auth_info.hdr.w_certificate_type)
     177                 :            :                         + sizeof(auth->auth_info.cert_type));
     178                 :            : 
     179                 :         50 :         return size;
     180                 :            : }
     181                 :            : 
     182                 :         32 : int get_auth_descriptor2(const void *buf, const size_t buflen, void **auth_buffer)
     183                 :            : {
     184                 :         32 :         const struct efi_variable_authentication_2 *auth = buf;
     185                 :            :         int auth_buffer_size;
     186                 :            :         size_t len;
     187                 :            : 
     188                 :         32 :         assert(auth_buffer != NULL);
     189                 :         32 :         if (buflen < sizeof(struct efi_variable_authentication_2)
     190                 :         32 :             || !buf)
     191                 :          0 :                         return OPAL_PARAMETER;
     192                 :            : 
     193                 :         32 :         len = get_pkcs7_len(auth);
     194                 :            :         /* pkcs7 content length cannot be greater than buflen */ 
     195                 :         32 :         if (len > buflen)
     196                 :          0 :                 return OPAL_PARAMETER;
     197                 :            : 
     198                 :         32 :         auth_buffer_size = sizeof(auth->timestamp) + sizeof(auth->auth_info.hdr)
     199                 :         32 :                            + sizeof(auth->auth_info.cert_type) + len;
     200                 :            : 
     201                 :         32 :         if (auth_buffer_size > buflen)
     202                 :          1 :                 return OPAL_PARAMETER;
     203                 :            : 
     204                 :         31 :         *auth_buffer = zalloc(auth_buffer_size);
     205                 :         31 :         if (!(*auth_buffer))
     206                 :          0 :                 return OPAL_NO_MEM;
     207                 :            : 
     208                 :            :         /*
     209                 :            :          * Data = auth descriptor + new ESL data.
     210                 :            :          * Extracts only the auth descriptor from data.
     211                 :            :          */
     212                 :         31 :         memcpy(*auth_buffer, buf, auth_buffer_size);
     213                 :            : 
     214                 :         31 :         return auth_buffer_size;
     215                 :            : }
     216                 :            : 
     217                 :         20 : static bool validate_cert(char *signing_cert, int signing_cert_size)
     218                 :            : {
     219                 :            :         mbedtls_x509_crt x509;
     220                 :         20 :         char *x509_buf = NULL;
     221                 :            :         int rc;
     222                 :            : 
     223                 :         20 :         mbedtls_x509_crt_init(&x509);
     224                 :         20 :         rc = mbedtls_x509_crt_parse(&x509, signing_cert, signing_cert_size);
     225                 :            : 
     226                 :            :         /* If failure in parsing the certificate, exit */
     227                 :         20 :         if(rc) {
     228                 :          0 :                 prlog(PR_ERR, "X509 certificate parsing failed %04x\n", rc);
     229                 :          0 :                 return false;
     230                 :            :         }
     231                 :            : 
     232                 :         20 :         x509_buf = zalloc(CERT_BUFFER_SIZE);
     233                 :         20 :         rc = mbedtls_x509_crt_info(x509_buf, CERT_BUFFER_SIZE, "CRT:", &x509);
     234                 :            : 
     235                 :         20 :         mbedtls_x509_crt_free(&x509);
     236                 :         20 :         free(x509_buf);
     237                 :         20 :         x509_buf = NULL;
     238                 :            : 
     239                 :            :         /* If failure in reading the certificate, exit */
     240                 :         20 :         if (rc < 0)
     241                 :          0 :                 return false;
     242                 :            : 
     243                 :         20 :         return true;
     244                 :            : }
     245                 :            : 
     246                 :          6 : static bool validate_hash(uuid_t type, int size)
     247                 :            : {
     248                 :          6 :         if (uuid_equals(&type, &EFI_CERT_SHA1_GUID) && (size == 20))
     249                 :          0 :                 return true;
     250                 :            : 
     251                 :          6 :         if (uuid_equals(&type, &EFI_CERT_SHA224_GUID) && (size == 28))
     252                 :          0 :                 return true;
     253                 :            : 
     254                 :          6 :         if (uuid_equals(&type, &EFI_CERT_SHA256_GUID) && (size == 32))
     255                 :          1 :                 return true;
     256                 :            : 
     257                 :          5 :         if (uuid_equals(&type, &EFI_CERT_SHA384_GUID) && (size == 48))
     258                 :          0 :                 return true;
     259                 :            : 
     260                 :          5 :         if (uuid_equals(&type, &EFI_CERT_SHA512_GUID) && (size == 64))
     261                 :          1 :                 return true;
     262                 :            : 
     263                 :          4 :         return false;
     264                 :            : }
     265                 :            : 
     266                 :         28 : int validate_esl_list(const char *key, const char *esl, const size_t size)
     267                 :            : {
     268                 :         28 :         int count = 0;
     269                 :            :         int dsize;
     270                 :         28 :         char *data = NULL;
     271                 :         28 :         int eslvarsize = size;
     272                 :            :         int eslsize;
     273                 :         28 :         int rc = OPAL_SUCCESS;
     274                 :         28 :         EFI_SIGNATURE_LIST *list = NULL;
     275                 :            : 
     276                 :         50 :         while (eslvarsize > 0) {
     277                 :         31 :                 prlog(PR_DEBUG, "esl var size is %d offset is %lu\n", eslvarsize, size - eslvarsize);
     278                 :         31 :                 if (eslvarsize < sizeof(EFI_SIGNATURE_LIST)) {
     279                 :          1 :                         prlog(PR_ERR, "ESL with size %d is too small\n", eslvarsize);
     280                 :          1 :                         rc = OPAL_PARAMETER;
     281                 :          1 :                         break;
     282                 :            :                 }
     283                 :            : 
     284                 :            :                 /* Check Supported ESL Type */
     285                 :         30 :                 list = get_esl_signature_list(esl, eslvarsize);
     286                 :            : 
     287                 :         30 :                 if (!list)
     288                 :          0 :                         return OPAL_PARAMETER;
     289                 :            : 
     290                 :            :                 /* Calculate the size of the ESL */
     291                 :         30 :                 eslsize = le32_to_cpu(list->SignatureListSize);
     292                 :            : 
     293                 :            :                 /* If could not extract the size */
     294                 :         30 :                 if (eslsize <= 0) {
     295                 :          0 :                         prlog(PR_ERR, "Invalid size of the ESL: %u\n",
     296                 :            :                                         le32_to_cpu(list->SignatureListSize));
     297                 :          0 :                         rc = OPAL_PARAMETER;
     298                 :          0 :                         break;
     299                 :            :                 }
     300                 :            : 
     301                 :            :                 /* Extract the certificate from the ESL */
     302                 :         30 :                 dsize = get_esl_cert(esl, eslvarsize, &data);
     303                 :         30 :                 if (dsize < 0) {
     304                 :          3 :                         rc = dsize;
     305                 :          3 :                         break;
     306                 :            :                 }
     307                 :            : 
     308                 :         27 :                 if (key_equals(key, "dbx")) {
     309                 :          6 :                         if (!validate_hash(list->SignatureType, dsize)) {
     310                 :          4 :                                 prlog(PR_ERR, "No valid hash is found\n");
     311                 :          4 :                                 rc = OPAL_PARAMETER;
     312                 :          4 :                                 break;
     313                 :            :                         }
     314                 :            :                 } else {
     315                 :         21 :                        if (!uuid_equals(&list->SignatureType, &EFI_CERT_X509_GUID)
     316                 :         20 :                            || !validate_cert(data, dsize)) {
     317                 :          1 :                                 prlog(PR_ERR, "No valid cert is found\n");
     318                 :          1 :                                 rc = OPAL_PARAMETER;
     319                 :          1 :                                 break;
     320                 :            :                        }
     321                 :            :                 }
     322                 :            : 
     323                 :         22 :                 count++;
     324                 :            : 
     325                 :            :                 /* Look for the next ESL */
     326                 :         22 :                 esl = esl + eslsize;
     327                 :         22 :                 eslvarsize = eslvarsize - eslsize;
     328                 :         22 :                 free(data);
     329                 :            :                 /* Since we are going to allocate again in the next iteration */
     330                 :         22 :                 data = NULL;
     331                 :            :         }
     332                 :            : 
     333                 :         28 :         if (rc == OPAL_SUCCESS) {
     334                 :         19 :                 if (key_equals(key, "PK") && (count > 1)) {
     335                 :          1 :                         prlog(PR_ERR, "PK can only be one\n");
     336                 :          1 :                         rc = OPAL_PARAMETER;
     337                 :            :                 } else {
     338                 :         18 :                         rc = count;
     339                 :            :                 }
     340                 :            :         }
     341                 :            : 
     342                 :         28 :         free(data);
     343                 :            : 
     344                 :         28 :         prlog(PR_INFO, "Total ESLs are %d\n", rc);
     345                 :         28 :         return rc;
     346                 :            : }
     347                 :            : 
     348                 :            : /* Get the timestamp for the last update of the give key */
     349                 :         43 : static struct efi_time *get_last_timestamp(const char *key, char *last_timestamp)
     350                 :            : {
     351                 :         43 :         struct efi_time *timestamp = (struct efi_time*)last_timestamp;
     352                 :            : 
     353                 :         43 :         if (!last_timestamp)
     354                 :          0 :                 return NULL;
     355                 :            : 
     356                 :         43 :         if (key_equals(key, "PK"))
     357                 :         12 :                 return &timestamp[0];
     358                 :         31 :         else if (key_equals(key, "KEK"))
     359                 :         11 :                 return &timestamp[1];
     360                 :         20 :         else if (key_equals(key, "db"))
     361                 :         12 :                 return &timestamp[2];
     362                 :          8 :         else if (key_equals(key, "dbx"))
     363                 :          8 :                 return &timestamp[3];
     364                 :            :         else
     365                 :          0 :                 return NULL;
     366                 :            : }
     367                 :            : 
     368                 :         12 : int update_timestamp(const char *key, const struct efi_time *timestamp, char *last_timestamp)
     369                 :            : {
     370                 :            :         struct efi_time *prev;
     371                 :            : 
     372                 :         12 :         prev = get_last_timestamp(key, last_timestamp);
     373                 :         12 :         if (prev == NULL)
     374                 :          0 :                 return OPAL_INTERNAL_ERROR;
     375                 :            : 
     376                 :            :         /* Update with new timestamp */
     377                 :         12 :         memcpy(prev, timestamp, sizeof(struct efi_time));
     378                 :            : 
     379                 :         12 :         prlog(PR_DEBUG, "updated prev year is %d month %d day %d\n",
     380                 :            :                         le16_to_cpu(prev->year), prev->month, prev->day);
     381                 :            : 
     382                 :         12 :         return OPAL_SUCCESS;
     383                 :            : }
     384                 :            : 
     385                 :         62 : static uint64_t unpack_timestamp(const struct efi_time *timestamp)
     386                 :            : {
     387                 :         62 :         uint64_t val = 0;
     388                 :         62 :         uint16_t year = le16_to_cpu(timestamp->year);
     389                 :            : 
     390                 :            :         /* pad1, nanosecond, timezone, daylight and pad2 are meant to be zero */
     391                 :         62 :         val |= ((uint64_t) timestamp->pad1 & 0xFF) << 0;
     392                 :         62 :         val |= ((uint64_t) timestamp->second & 0xFF) << (1*8);
     393                 :         62 :         val |= ((uint64_t) timestamp->minute & 0xFF) << (2*8);
     394                 :         62 :         val |= ((uint64_t) timestamp->hour & 0xFF) << (3*8);
     395                 :         62 :         val |= ((uint64_t) timestamp->day & 0xFF) << (4*8);
     396                 :         62 :         val |= ((uint64_t) timestamp->month & 0xFF) << (5*8);
     397                 :         62 :         val |= ((uint64_t) year) << (6*8);
     398                 :            : 
     399                 :         62 :         return val;
     400                 :            : }
     401                 :            : 
     402                 :         31 : int check_timestamp(const char *key, const struct efi_time *timestamp,
     403                 :            :                     char *last_timestamp)
     404                 :            : {
     405                 :            :         struct efi_time *prev;
     406                 :            :         uint64_t new;
     407                 :            :         uint64_t last;
     408                 :            : 
     409                 :         31 :         prev = get_last_timestamp(key, last_timestamp);
     410                 :         31 :         if (prev == NULL)
     411                 :          0 :                 return OPAL_INTERNAL_ERROR;
     412                 :            : 
     413                 :         31 :         prlog(PR_DEBUG, "timestamp year is %d month %d day %d\n",
     414                 :            :                         le16_to_cpu(timestamp->year), timestamp->month,
     415                 :            :                         timestamp->day);
     416                 :         31 :         prlog(PR_DEBUG, "prev year is %d month %d day %d\n",
     417                 :            :                         le16_to_cpu(prev->year), prev->month, prev->day);
     418                 :            : 
     419                 :         31 :         new = unpack_timestamp(timestamp);
     420                 :         31 :         last = unpack_timestamp(prev);
     421                 :            : 
     422                 :         31 :         if (new > last)
     423                 :         28 :                 return OPAL_SUCCESS;
     424                 :            : 
     425                 :          3 :         return OPAL_PERMISSION;
     426                 :            : }
     427                 :            : 
     428                 :            : /* Extract PKCS7 from the authentication header */
     429                 :         18 : static mbedtls_pkcs7* get_pkcs7(const struct efi_variable_authentication_2 *auth)
     430                 :            : {
     431                 :         18 :         char *checkpkcs7cert = NULL;
     432                 :            :         size_t len;
     433                 :         18 :         mbedtls_pkcs7 *pkcs7 = NULL;
     434                 :            :         int rc;
     435                 :            : 
     436                 :         18 :         len = get_pkcs7_len(auth);
     437                 :            : 
     438                 :         18 :         pkcs7 = malloc(sizeof(struct mbedtls_pkcs7));
     439                 :         18 :         if (!pkcs7)
     440                 :          0 :                 return NULL;
     441                 :            : 
     442                 :         18 :         mbedtls_pkcs7_init(pkcs7);
     443                 :         18 :         rc = mbedtls_pkcs7_parse_der( auth->auth_info.cert_data, len, pkcs7);
     444                 :         18 :         if (rc <= 0) {
     445                 :          1 :                 prlog(PR_ERR, "Parsing pkcs7 failed %04x\n", rc);
     446                 :          1 :                 goto out;
     447                 :            :         }
     448                 :            : 
     449                 :         17 :         checkpkcs7cert = zalloc(CERT_BUFFER_SIZE);
     450                 :         17 :         if (!checkpkcs7cert)
     451                 :          0 :                 goto out;
     452                 :            : 
     453                 :         17 :         rc = mbedtls_x509_crt_info(checkpkcs7cert, CERT_BUFFER_SIZE, "CRT:",
     454                 :         17 :                                    &(pkcs7->signed_data.certs));
     455                 :         17 :         if (rc < 0) {
     456                 :          0 :                 prlog(PR_ERR, "Failed to parse the certificate in PKCS7 structure\n");
     457                 :          0 :                 free(checkpkcs7cert);
     458                 :          0 :                 goto out;
     459                 :            :         }
     460                 :            : 
     461                 :         17 :         prlog(PR_DEBUG, "%s \n", checkpkcs7cert);
     462                 :         17 :         free(checkpkcs7cert);
     463                 :         17 :         return pkcs7;
     464                 :            : 
     465                 :          1 : out:
     466                 :          1 :         mbedtls_pkcs7_free(pkcs7);
     467                 :          1 :         free(pkcs7);
     468                 :          1 :         pkcs7 = NULL;
     469                 :          1 :         return pkcs7;
     470                 :            : }
     471                 :            : 
     472                 :            : /* Verify the PKCS7 signature on the signed data. */
     473                 :         18 : static int verify_signature(const struct efi_variable_authentication_2 *auth,
     474                 :            :                             const char *hash, const size_t hash_len,
     475                 :            :                             const struct secvar *avar)
     476                 :            : {
     477                 :         18 :         mbedtls_pkcs7 *pkcs7 = NULL;
     478                 :            :         mbedtls_x509_crt x509;
     479                 :            :         mbedtls_md_type_t md_alg;
     480                 :         18 :         char *signing_cert = NULL;
     481                 :         18 :         char *x509_buf = NULL;
     482                 :            :         int signing_cert_size;
     483                 :         18 :         int rc = 0;
     484                 :            :         char *errbuf;
     485                 :            :         int eslvarsize;
     486                 :            :         int eslsize;
     487                 :         18 :         int offset = 0;
     488                 :            : 
     489                 :         18 :         if (!auth)
     490                 :          0 :                 return OPAL_PARAMETER;
     491                 :            : 
     492                 :            :         /* Extract the pkcs7 from the auth structure */
     493                 :         18 :         pkcs7 = get_pkcs7(auth);
     494                 :            :         /* Failure to parse pkcs7 implies bad input. */
     495                 :         18 :         if (!pkcs7)
     496                 :          1 :                 return OPAL_PARAMETER;
     497                 :            : 
     498                 :            :         /*
     499                 :            :          * We only support sha256, which has a hash length of 32.
     500                 :            :          * If the alg is not sha256, then we should bail now.
     501                 :            :          */
     502                 :         17 :         rc = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers,
     503                 :            :                                     &md_alg);
     504                 :         17 :         if (rc != 0) {
     505                 :          0 :                 prlog(PR_ERR, "Failed to get the Digest Algorithm Identifier: %d\n", rc);
     506                 :          0 :                 rc = OPAL_PARAMETER;
     507                 :          0 :                 goto err_pkcs7;
     508                 :            :         }
     509                 :            : 
     510                 :         17 :         if (md_alg != MBEDTLS_MD_SHA256) {
     511                 :          2 :                 prlog(PR_ERR, "Unexpected digest algorithm: expected %d (SHA-256), got %d\n",
     512                 :            :                       MBEDTLS_MD_SHA256, md_alg);
     513                 :          2 :                 rc = OPAL_PARAMETER;
     514                 :          2 :                 goto err_pkcs7;
     515                 :            :         }
     516                 :            : 
     517                 :         15 :         prlog(PR_INFO, "Load the signing certificate from the keystore");
     518                 :            : 
     519                 :         15 :         eslvarsize = avar->data_size;
     520                 :            : 
     521                 :            :         /* Variable is not empty */
     522                 :         23 :         while (eslvarsize > 0) {
     523                 :         17 :                 prlog(PR_DEBUG, "esl var size is %d offset is %d\n", eslvarsize, offset);
     524                 :         17 :                 if (eslvarsize < sizeof(EFI_SIGNATURE_LIST)) {
     525                 :          1 :                         rc = OPAL_INTERNAL_ERROR;
     526                 :          1 :                         prlog(PR_ERR, "ESL data is corrupted\n");
     527                 :          1 :                         break;
     528                 :            :                 }
     529                 :            : 
     530                 :            :                 /* Calculate the size of the ESL */
     531                 :         16 :                 eslsize = get_esl_signature_list_size(avar->data + offset,
     532                 :            :                                                       eslvarsize);
     533                 :            :                 /* If could not extract the size */
     534                 :         16 :                 if (eslsize <= 0) {
     535                 :          0 :                         rc = OPAL_PARAMETER;
     536                 :          0 :                         break;
     537                 :            :                 }
     538                 :            : 
     539                 :            :                 /* Extract the certificate from the ESL */
     540                 :         16 :                 signing_cert_size = get_esl_cert(avar->data + offset,
     541                 :            :                                                  eslvarsize, &signing_cert);
     542                 :         16 :                 if (signing_cert_size < 0) {
     543                 :          0 :                         rc = signing_cert_size;
     544                 :          0 :                         break;
     545                 :            :                 }
     546                 :            : 
     547                 :         16 :                 mbedtls_x509_crt_init(&x509);
     548                 :         16 :                 rc = mbedtls_x509_crt_parse(&x509,
     549                 :            :                                             signing_cert,
     550                 :            :                                             signing_cert_size);
     551                 :            : 
     552                 :            :                 /* This should not happen, unless something corrupted in PNOR */
     553                 :         16 :                 if(rc) {
     554                 :          0 :                         prlog(PR_ERR, "X509 certificate parsing failed %04x\n", rc);
     555                 :          0 :                         rc = OPAL_INTERNAL_ERROR;
     556                 :          0 :                         break;
     557                 :            :                 }
     558                 :            : 
     559                 :         16 :                 x509_buf = zalloc(CERT_BUFFER_SIZE);
     560                 :         16 :                 rc = mbedtls_x509_crt_info(x509_buf,
     561                 :            :                                            CERT_BUFFER_SIZE,
     562                 :            :                                            "CRT:",
     563                 :            :                                            &x509);
     564                 :            : 
     565                 :            :                 /* This should not happen, unless something corrupted in PNOR */
     566                 :         16 :                 if (rc < 0) {
     567                 :          0 :                         free(x509_buf);
     568                 :          0 :                         rc = OPAL_INTERNAL_ERROR;
     569                 :          0 :                         break;
     570                 :            :                 }
     571                 :            : 
     572                 :         16 :                 prlog(PR_INFO, "%s \n", x509_buf);
     573                 :         16 :                 free(x509_buf);
     574                 :         16 :                 x509_buf = NULL;
     575                 :            : 
     576                 :         16 :                 rc = mbedtls_pkcs7_signed_hash_verify(pkcs7, &x509, hash, hash_len);
     577                 :            : 
     578                 :            :                 /* If you find a signing certificate, you are done */
     579                 :         16 :                 if (rc == 0) {
     580                 :          8 :                         prlog(PR_INFO, "Signature Verification passed\n");
     581                 :          8 :                         mbedtls_x509_crt_free(&x509);
     582                 :          8 :                         break;
     583                 :            :                 } else {
     584                 :          8 :                         errbuf = zalloc(MBEDTLS_ERR_BUFFER_SIZE);
     585                 :          8 :                         mbedtls_strerror(rc, errbuf, MBEDTLS_ERR_BUFFER_SIZE);
     586                 :          8 :                         prlog(PR_ERR, "Signature Verification failed %02x %s\n",
     587                 :            :                                         rc, errbuf);
     588                 :          8 :                         free(errbuf);
     589                 :          8 :                         rc = OPAL_PERMISSION;
     590                 :            :                 }
     591                 :            : 
     592                 :            : 
     593                 :            :                 /* Look for the next ESL */
     594                 :          8 :                 offset = offset + eslsize;
     595                 :          8 :                 eslvarsize = eslvarsize - eslsize;
     596                 :          8 :                 mbedtls_x509_crt_free(&x509);
     597                 :          8 :                 free(signing_cert);
     598                 :            :                 /* Since we are going to allocate again in the next iteration */
     599                 :          8 :                 signing_cert = NULL;
     600                 :            : 
     601                 :            :         }
     602                 :            : 
     603                 :         15 :         free(signing_cert);
     604                 :         17 : err_pkcs7:
     605                 :         17 :         mbedtls_pkcs7_free(pkcs7);
     606                 :         17 :         free(pkcs7);
     607                 :            : 
     608                 :         17 :         return rc;
     609                 :            : }
     610                 :            : 
     611                 :            : /* 
     612                 :            :  * Create the hash of the buffer
     613                 :            :  * name || vendor guid || attributes || timestamp || newcontent
     614                 :            :  * which is submitted as signed by the user.
     615                 :            :  * Returns the sha256 hash, else NULL.
     616                 :            :  */
     617                 :         14 : static char *get_hash_to_verify(const char *key, const char *new_data,
     618                 :            :                                 const size_t new_data_size,
     619                 :            :                                 const struct efi_time *timestamp)
     620                 :            : {
     621                 :         14 :         le32 attr = cpu_to_le32(SECVAR_ATTRIBUTES);
     622                 :            :         size_t varlen;
     623                 :            :         char *wkey;
     624                 :            :         uuid_t guid;
     625                 :         14 :         unsigned char *hash = NULL;
     626                 :            :         const mbedtls_md_info_t *md_info;
     627                 :            :         mbedtls_md_context_t ctx;
     628                 :            :         int rc;
     629                 :            : 
     630                 :         14 :         md_info = mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 );
     631                 :         14 :         mbedtls_md_init(&ctx);
     632                 :            : 
     633                 :         14 :         rc = mbedtls_md_setup(&ctx, md_info, 0);
     634                 :         14 :         if (rc)
     635                 :          0 :                 goto out;
     636                 :            : 
     637                 :         14 :         rc = mbedtls_md_starts(&ctx);
     638                 :         14 :         if (rc)
     639                 :          0 :                 goto out;
     640                 :            : 
     641                 :         14 :         if (key_equals(key, "PK")
     642                 :         12 :             || key_equals(key, "KEK"))
     643                 :          5 :                 guid = EFI_GLOBAL_VARIABLE_GUID;
     644                 :          9 :         else if (key_equals(key, "db")
     645                 :          1 :             || key_equals(key, "dbx"))
     646                 :          9 :                 guid = EFI_IMAGE_SECURITY_DATABASE_GUID;
     647                 :            :         else
     648                 :          0 :                 goto out;
     649                 :            : 
     650                 :            :         /* Expand char name to wide character width */
     651                 :         14 :         varlen = strlen(key) * 2;
     652                 :         14 :         wkey = char_to_wchar(key, strlen(key));
     653                 :         14 :         rc = mbedtls_md_update(&ctx, wkey, varlen);
     654                 :         14 :         free(wkey);
     655                 :         14 :         if (rc) 
     656                 :          0 :                 goto out;
     657                 :            : 
     658                 :         14 :         rc = mbedtls_md_update(&ctx, (const unsigned char *)&guid, sizeof(guid));
     659                 :         14 :         if (rc)
     660                 :          0 :                 goto out;
     661                 :            : 
     662                 :         14 :         rc = mbedtls_md_update(&ctx, (const unsigned char *)&attr, sizeof(attr));
     663                 :         14 :         if (rc)
     664                 :          0 :                 goto out;
     665                 :            : 
     666                 :         14 :         rc = mbedtls_md_update(&ctx, (const unsigned char *)timestamp,
     667                 :            :                                sizeof(struct efi_time));
     668                 :         14 :         if (rc)
     669                 :          0 :                 goto out;
     670                 :            : 
     671                 :         14 :         rc = mbedtls_md_update(&ctx, new_data, new_data_size);
     672                 :         14 :         if (rc)
     673                 :          0 :                 goto out;
     674                 :            : 
     675                 :         14 :         hash = zalloc(32);
     676                 :         14 :         if (!hash)
     677                 :          0 :                 goto out;
     678                 :         14 :         rc = mbedtls_md_finish(&ctx, hash);
     679                 :         14 :         if (rc) {
     680                 :          0 :                 free(hash);
     681                 :          0 :                 hash = NULL;
     682                 :            :         }
     683                 :            : 
     684                 :         14 : out:
     685                 :         14 :         mbedtls_md_free(&ctx);
     686                 :         14 :         return hash;
     687                 :            : }
     688                 :            : 
     689                 :         34 : bool is_pkcs7_sig_format(const void *data)
     690                 :            : {
     691                 :         34 :         const struct efi_variable_authentication_2 *auth = data;
     692                 :         34 :         uuid_t pkcs7_guid = EFI_CERT_TYPE_PKCS7_GUID;
     693                 :            : 
     694                 :         34 :         return !memcmp(&auth->auth_info.cert_type, &pkcs7_guid, 16);
     695                 :            : }
     696                 :            : 
     697                 :         32 : int process_update(const struct secvar *update, char **newesl,
     698                 :            :                    int *new_data_size, struct efi_time *timestamp,
     699                 :            :                    struct list_head *bank, char *last_timestamp)
     700                 :            : {
     701                 :         32 :         struct efi_variable_authentication_2 *auth = NULL;
     702                 :         32 :         void *auth_buffer = NULL;
     703                 :         32 :         int auth_buffer_size = 0;
     704                 :            :         const char *key_authority[3];
     705                 :         32 :         char *hash = NULL;
     706                 :         32 :         struct secvar *avar = NULL;
     707                 :         32 :         int rc = 0;
     708                 :            :         int i;
     709                 :            : 
     710                 :            :         /* We need to split data into authentication descriptor and new ESL */
     711                 :         32 :         auth_buffer_size = get_auth_descriptor2(update->data,
     712                 :         32 :                                                 update->data_size,
     713                 :            :                                                 &auth_buffer);
     714                 :         32 :         if ((auth_buffer_size < 0)
     715                 :         31 :              || (update->data_size < auth_buffer_size)) {
     716                 :          1 :                 prlog(PR_ERR, "Invalid auth buffer size\n");
     717                 :          1 :                 rc = auth_buffer_size;
     718                 :          1 :                 goto out;
     719                 :            :         }
     720                 :            : 
     721                 :         31 :         auth = auth_buffer;
     722                 :            : 
     723                 :         31 :         if (!timestamp) {
     724                 :          0 :                 rc = OPAL_INTERNAL_ERROR;
     725                 :          0 :                 goto out;
     726                 :            :         }
     727                 :            : 
     728                 :         31 :         memcpy(timestamp, auth_buffer, sizeof(struct efi_time));
     729                 :            : 
     730                 :         31 :         rc = check_timestamp(update->key, timestamp, last_timestamp);
     731                 :            :         /* Failure implies probably an older command being resubmitted */
     732                 :         31 :         if (rc != OPAL_SUCCESS) {
     733                 :          3 :                 prlog(PR_ERR, "Timestamp verification failed for key %s\n", update->key);
     734                 :          3 :                 goto out;
     735                 :            :         }
     736                 :            : 
     737                 :            :         /* Calculate the size of new ESL data */
     738                 :         28 :         *new_data_size = update->data_size - auth_buffer_size;
     739                 :         28 :         if (*new_data_size < 0) {
     740                 :          0 :                 prlog(PR_ERR, "Invalid new ESL (new data content) size\n");
     741                 :          0 :                 rc = OPAL_PARAMETER;
     742                 :          0 :                 goto out;
     743                 :            :         }
     744                 :         28 :         *newesl = zalloc(*new_data_size);
     745                 :         28 :         if (!(*newesl)) {
     746                 :          0 :                 rc = OPAL_NO_MEM;
     747                 :          0 :                 goto out;
     748                 :            :         }
     749                 :         28 :         memcpy(*newesl, update->data + auth_buffer_size, *new_data_size);
     750                 :            : 
     751                 :            :         /* Validate the new ESL is in right format */
     752                 :         28 :         rc = validate_esl_list(update->key, *newesl, *new_data_size);
     753                 :         28 :         if (rc < 0) {
     754                 :         10 :                 prlog(PR_ERR, "ESL validation failed for key %s with error %04x\n",
     755                 :            :                       update->key, rc);
     756                 :         10 :                 goto out;
     757                 :            :         }
     758                 :            : 
     759                 :         18 :         if (setup_mode) {
     760                 :          4 :                 rc = OPAL_SUCCESS;
     761                 :          4 :                 goto out;
     762                 :            :         }
     763                 :            : 
     764                 :            :         /* Prepare the data to be verified */
     765                 :         14 :         hash = get_hash_to_verify(update->key, *newesl, *new_data_size,
     766                 :            :                                 timestamp);
     767                 :         14 :         if (!hash) {
     768                 :          0 :                 rc = OPAL_INTERNAL_ERROR;
     769                 :          0 :                 goto out;
     770                 :            :         }
     771                 :            : 
     772                 :            :         /* Get the authority to verify the signature */
     773                 :         14 :         get_key_authority(key_authority, update->key);
     774                 :            : 
     775                 :            :         /*
     776                 :            :          * Try for all the authorities that are allowed to sign.
     777                 :            :          * For eg. db/dbx can be signed by both PK or KEK
     778                 :            :          */
     779                 :         27 :         for (i = 0; key_authority[i] != NULL; i++) {
     780                 :         21 :                 prlog(PR_DEBUG, "key is %s\n", update->key);
     781                 :         21 :                 prlog(PR_DEBUG, "key authority is %s\n", key_authority[i]);
     782                 :         21 :                 avar = find_secvar(key_authority[i],
     783                 :         21 :                                     strlen(key_authority[i]) + 1,
     784                 :            :                                     bank);
     785                 :         21 :                 if (!avar || !avar->data_size)
     786                 :          3 :                         continue;
     787                 :            : 
     788                 :            :                 /* Verify the signature. sha256 is 32 bytes long. */
     789                 :         18 :                 rc = verify_signature(auth, hash, 32, avar);
     790                 :            : 
     791                 :            :                 /* Break if signature verification is successful */
     792                 :         18 :                 if (rc == OPAL_SUCCESS) {
     793                 :          8 :                         prlog(PR_INFO, "Key %s successfully verified by authority %s\n", update->key, key_authority[i]);
     794                 :          8 :                         break;
     795                 :            :                 }
     796                 :            :         }
     797                 :            : 
     798                 :          6 : out:
     799                 :         32 :         free(auth_buffer);
     800                 :         32 :         free(hash);
     801                 :            : 
     802                 :         32 :         return rc;
     803                 :            : }

Generated by: LCOV version 1.14