Le sam. 19 oct. 2024, 15:51, chench246 <chench...@gmail.com> a écrit :

> From: chench246 <chench...@hotmail.com>
>
> TPCM(Trusted Platform Control Module) is a Chinese standard and is
> compatible with TPM.
>
Before I review the patch: can you explain about compatibility. Of you day
that it's compatible with TPM, why doesn't normal TPM code work?

---
>  grub-core/Makefile.core.def   |   7 ++
>  grub-core/commands/efi/tpcm.c | 163 ++++++++++++++++++++++++++++++++++
>  grub-core/commands/tpcm.c     |  99 +++++++++++++++++++++
>  include/grub/efi/tpcm.h       |  60 +++++++++++++
>  include/grub/err.h            |   3 +-
>  5 files changed, 331 insertions(+), 1 deletion(-)
>  create mode 100755 grub-core/commands/efi/tpcm.c
>  create mode 100755 grub-core/commands/tpcm.c
>  create mode 100644 include/grub/efi/tpcm.h
>
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index 063ef5dd7..f1250601b 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -2562,6 +2562,13 @@ module = {
>    enable = efi;
>  };
>
> +module = {
> +  name = tpcm;
> +  common = commands/tpcm.c;
> +  efi = commands/efi/tpcm.c;
> +  enable = x86_64_efi;
> +};
> +
>  module = {
>    name = tr;
>    common = commands/tr.c;
> diff --git a/grub-core/commands/efi/tpcm.c b/grub-core/commands/efi/tpcm.c
> new file mode 100755
> index 000000000..bc97e800c
> --- /dev/null
> +++ b/grub-core/commands/efi/tpcm.c
> @@ -0,0 +1,163 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2018  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + *  EFI TPCM support code.
> + */
> +
> +#include <grub/err.h>
> +#include <grub/efi/tpcm.h>
> +
> +
> +static grub_uint32_t g_measured_id = STAGE_START;
> +
> +/*
> +    get_tpcm_stage:
> +      TPCM does not make a distinction with the type of
> +    measured target, so we use g_measured_id directly
> +    for the stage.
> + */
> +static grub_uint32_t get_tpcm_stage(void)
> +{
> +    grub_uint32_t stage = STAGE_INVALID;
> +
> +    stage = g_measured_id;
> +
> +    if (stage < STAGE_START || stage > STAGE_END)
> +        stage = STAGE_INVALID;
> +
> +    return stage;
> +}
> +
> +/*
> +    update_measured_id:
> +      update g_measured_id +1 every time measured, and g_measured_id
> +    will never be decreased.
> + */
> +static void update_measured_id(void)
> +{
> +    g_measured_id++;
> +}
> +
> +/*
> +    measure_memory:
> +      measure the memery region--(addr, size) through the TPCM protocol.
> +    if TPCM protocol is not exist in BIOS, it will return SUCC to keep
> +    compatible with non-measurement-support bios; if TPCM protocol is
> +    exist but not enabled, it will also return SUCC.
> + */
> +static grub_err_t measure_memory(enum grub_file_type type
> __attribute__((unused)),
> +                                 char *desc,
> +                                 grub_addr_t addr,
> +                                 grub_size_t size)
> +{
> +    grub_efi_handle_t   *handles = 0;
> +    grub_efi_uintn_t    num_handles;
> +    grub_efi_handle_t   grub_c2p_handle = 0;
> +    grub_err_t  test_c2p_err = GRUB_ERR_BAD_OS;
> +    grub_guid_t         c2p_guid = C2PGUID;
> +    grub_uint32_t       measure_result = 0;
> +    grub_uint32_t       control_result = 0;
> +    grub_efi_boolean_t    verify_enable = 0;
> +    grub_size_t         desc_len = 0;
> +
> +    handles = grub_efi_locate_handle(GRUB_EFI_BY_PROTOCOL, &c2p_guid,
> NULL, &num_handles);
> +    if (handles && (num_handles > 0))
> +    {
> +        struct c2p_protocol *c2p;
> +
> +        grub_c2p_handle = handles[0];
> +        grub_dprintf ("tpcm", "measue memory addr 0x%lx size 0x%lx  \n",
> addr, size);
> +        c2p = grub_efi_open_protocol(grub_c2p_handle, &c2p_guid,
> +
> GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> +        if (c2p)
> +        {
> +            verify_enable = c2p->verify_is_enabled (c2p);
> +            if (verify_enable)
> +            {
> +                struct addr_range range;
> +                grub_efi_status_t status = 0;
> +                grub_uint32_t stage = STAGE_INVALID;
> +
> +                range.start  = addr;
> +                range.length = size;
> +
> +                stage = get_tpcm_stage();
> +                if (stage != STAGE_INVALID)
> +                {
> +                    desc_len = grub_strlen(desc) + 1;
> +                    status = c2p->verify_raw (c2p, stage,
> (grub_uint64_t)desc, desc_len, 1, &range, &measure_result, &control_result);
> +                    if ((!status) && ((control_result &
> MEASURE_ACTION_MASK) == 0) )
> +                    {
> +                        grub_dprintf ("tpcm", "verify_raw success.
> stage[%d]desc:[%s]\n", stage, desc);
> +                        test_c2p_err = GRUB_ERR_NONE;
> +                    }
> +                    else
> +                    {
> +                        grub_dprintf ("tpcm", "verify_raw error\n");
> +                        while(1)
> +                        {
> +                            grub_error (GRUB_ERR_TPCM_VERIFY, "tpcm
> verify error. stage[%d]desc[%s]\n", stage, desc);
> +                            asm volatile ("hlt");
> +                        }
> +                    }
> +                }
> +                else {
> +                    grub_dprintf ("tpcm", "invalid stage\n");
> +                }
> +
> +                update_measured_id();
> +
> +            }
> +            else {
> +                grub_dprintf ("tpcm", "image verify not enabled\n");
> +                test_c2p_err = GRUB_ERR_NONE;
> +            }
> +        }
> +        else
> +            grub_dprintf ("tpcm", "open c2p protocol failed\n");
> +    }
> +    else
> +    {
> +        /* keep compatible with non-measurement-support bios. */
> +        grub_dprintf ("tpcm", "not found C2P protocol\n");
> +        test_c2p_err = GRUB_ERR_NONE;
> +    }
> +
> +    return test_c2p_err;
> +}
> +
> +/*
> +    grub_tpcm_measure_memory:
> + */
> +grub_err_t grub_tpcm_measure_memory(void *context, grub_addr_t buf,
> grub_size_t size)
> +{
> +    char *p_context = (char *)context;
> +    char *p, *p_desc;
> +    char tmp[TPCM_MAX_BUF_SIZE] = {'0'};
> +    enum grub_file_type type;
> +
> +    if (!p_context)
> +        return GRUB_ERR_BUG;
> +
> +    p = grub_strchr(p_context, '|');
> +    p_desc = p + 1;
> +    grub_memcpy(tmp, p_context, (p-p_context));
> +    type = grub_strtoul(tmp, 0, 10);
> +
> +    return measure_memory(type, p_desc, buf, size);
> +}
> +
> diff --git a/grub-core/commands/tpcm.c b/grub-core/commands/tpcm.c
> new file mode 100755
> index 000000000..1c8bd77ce
> --- /dev/null
> +++ b/grub-core/commands/tpcm.c
> @@ -0,0 +1,99 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2018  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + *  Core TPCM support code.
> + */
> +
> +#include <grub/err.h>
> +#include <grub/verify.h>
> +#include <grub/dl.h>
> +#include <grub/efi/tpcm.h>
> +
> +GRUB_MOD_LICENSE ("GPLv3+");
> +
> +static char context_buf[TPCM_MAX_BUF_SIZE];
> +
> +static grub_err_t grub_tpcm_verify_init(grub_file_t io,
> +                      enum grub_file_type type,
> +                      void **context,
> +                      enum grub_verify_flags *flags)
> +{
> +    grub_memset(context_buf, 0, TPCM_MAX_BUF_SIZE);
> +    grub_snprintf(context_buf, TPCM_MAX_BUF_SIZE, "%d|%s", (type &
> GRUB_FILE_TYPE_MASK), io->name);
> +    *context = context_buf;
> +    *flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK;
> +
> +    return GRUB_ERR_NONE;
> +}
> +
> +static grub_err_t grub_tpcm_verify_write(void *context, void *buf ,
> grub_size_t size )
> +{
> +    return grub_tpcm_measure_memory(context, (grub_addr_t)buf, size);
> +}
> +
> +static grub_err_t grub_tpcm_verify_string (char *str, enum
> grub_verify_string_type type)
> +{
> +    const char *prefix = NULL;
> +    char *description, *context;
> +    grub_err_t status;
> +
> +    switch (type)
> +    {
> +    case GRUB_VERIFY_KERNEL_CMDLINE:
> +      prefix = "kernel_cmdline: ";
> +      break;
> +    case GRUB_VERIFY_MODULE_CMDLINE:
> +      prefix = "module_cmdline: ";
> +      break;
> +    case GRUB_VERIFY_COMMAND:
> +      prefix = "grub_cmd: ";
> +      break;
> +    }
> +
> +    context = grub_zalloc(grub_strlen (str) + grub_strlen (prefix) + 1 +
> 4);  /* 4 for type */
> +    if (!context)
> +        return grub_errno;
> +
> +    grub_snprintf(context, 4, "%d|", (type & GRUB_FILE_TYPE_MASK));
> +    description = context + grub_strlen(context);
> +    grub_memcpy(description, prefix, grub_strlen (prefix));
> +    grub_memcpy(description + grub_strlen (prefix), str, grub_strlen
> (str) + 1);
> +
> +    status = grub_tpcm_measure_memory(context, (grub_addr_t)str,
> grub_strlen(str));
> +
> +    grub_free(context);
> +
> +    return status;
> +}
> +
> +struct grub_file_verifier grub_tpcm_verifier = {
> +    .name = "tpcm",
> +    .init  = grub_tpcm_verify_init,
> +    .write = grub_tpcm_verify_write,
> +    .verify_string = grub_tpcm_verify_string,
> +};
> +
> +GRUB_MOD_INIT (tpcm)
> +{
> +    grub_verifier_register(&grub_tpcm_verifier);
> +}
> +
> +GRUB_MOD_FINI (tpcm)
> +{
> +    grub_verifier_unregister(&grub_tpcm_verifier);
> +}
> +
> diff --git a/include/grub/efi/tpcm.h b/include/grub/efi/tpcm.h
> new file mode 100644
> index 000000000..a4e0c765a
> --- /dev/null
> +++ b/include/grub/efi/tpcm.h
> @@ -0,0 +1,60 @@
> +/*
> + *  GRUB  --  GRand Unified Bootloader
> + *  Copyright (C) 2018  Free Software Foundation, Inc.
> + *
> + *  GRUB is free software: you can redistribute it and/or modify
> + *  it under the terms of the GNU General Public License as published by
> + *  the Free Software Foundation, either version 3 of the License, or
> + *  (at your option) any later version.
> + *
> + *  GRUB is distributed in the hope that it will be useful,
> + *  but WITHOUT ANY WARRANTY; without even the implied warranty of
> + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + *  GNU General Public License for more details.
> + *
> + *  You should have received a copy of the GNU General Public License
> + *  along with GRUB.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef GRUB_EFI_TPCM_HEADER
> +#define GRUB_EFI_TPCM_HEADER 1
> +
> +#include <grub/file.h>
> +#include <grub/efi/api.h>
> +#include <grub/efi/efi.h>
> +
> +#define C2PGUID         {0xf89ab5cd, 0x2829, 0x422f, {0xa5, 0xf3, 0x03,
> 0x28, 0xe0, 0x6c, 0xfc, 0xbb}}
> +#define MEASURE_RESULT_MASK          (0xff00)
> +#define MEASURE_RESULT_SHIFT         (16)
> +#define MEASURE_ACTION_MASK          (0x1)
> +#define TPCM_MAX_BUF_SIZE            128
> +
> +/*
> +   stage layout:
> +     2000~2999: +1 every time
> +*/
> +
> +#define STAGE_START      2000
> +#define STAGE_END        2999
> +#define STAGE_INVALID    3000
> +
> +struct addr_range {
> +    grub_uint64_t start;
> +    grub_uint64_t length;
> +};
> +struct c2p_protocol {
> +    grub_efi_status_t (__grub_efi_api *verify_raw) (struct c2p_protocol
> *this,
> +                                    grub_uint32_t measure_stage,
> +                                    grub_uint64_t image_info,
> +                                    grub_uint32_t image_info_size,
> +                                    grub_uint32_t num_addr_range,
> +                                    struct addr_range ranges[],
> +                                    grub_uint32_t *measure_result,
> +                                    grub_uint32_t *control_result);
> +    grub_efi_boolean_t (__grub_efi_api *verify_is_enabled)(struct
> c2p_protocol *this);
> +};
> +typedef struct c2p_protocol c2p_protocol_t;
> +
> +grub_err_t grub_tpcm_measure_memory(void *context, grub_addr_t buf,
> grub_size_t size);
> +
> +#endif
> diff --git a/include/grub/err.h b/include/grub/err.h
> index 1c07034cd..f5268dd47 100644
> --- a/include/grub/err.h
> +++ b/include/grub/err.h
> @@ -73,7 +73,8 @@ typedef enum
>      GRUB_ERR_NET_NO_DOMAIN,
>      GRUB_ERR_EOF,
>      GRUB_ERR_BAD_SIGNATURE,
> -    GRUB_ERR_BAD_FIRMWARE
> +    GRUB_ERR_BAD_FIRMWARE,
> +    GRUB_ERR_TPCM_VERIFY
>    }
>  grub_err_t;
>
> --
> 2.17.1
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to