On Mon, Oct 21, 2024 at 07:11:00PM -0400, Stefan Berger wrote:
> 
> 
> On 10/21/24 4:07 AM, Gary Lin wrote:
> > From: Hernan Gatta <hega...@linux.microsoft.com>
> > 
> > To utilize the key protectors framework, there must be a way to protect
> > full-disk encryption keys in the first place. The grub-protect tool
> > includes support for the TPM2 key protector but other protectors that
> > require setup ahead of time can be supported in the future.
> > 
> > For the TPM2 key protector, the intended flow is for a user to have a
> > LUKS 1 or LUKS 2-protected fully-encrypted disk. The user then creates a
> > new LUKS key file, say by reading /dev/urandom into a file, and creates
> > a new LUKS key slot for this key. Then, the user invokes the grub-protect
> > tool to seal this key file to a set of PCRs using the system's TPM 2.0.
> > The resulting sealed key file is stored in an unencrypted partition such
> > as the EFI System Partition (ESP) so that GRUB may read it. The user also
> > has to ensure the cryptomount command is included in GRUB's boot script
> > and that it carries the requisite key protector (-P) parameter.
> > 
> > Sample usage:
> > 
> > $ dd if=/dev/urandom of=luks-key bs=1 count=32
> > $ sudo cryptsetup luksAddKey /dev/sdb1 luks-key --pbkdf=pbkdf2 --hash=sha512
> > 
> > To seal the key with TPM 2.0 Key File (recommended):
> > 
> > $ sudo grub-protect --action=add \
> >                      --protector=tpm2 \
> >                      --tpm2-pcrs=0,2,4,7,9 \
> >                      --tpm2key \
> >                      --tpm2-keyfile=luks-key \
> >                      --tpm2-outfile=/boot/efi/efi/grub/sealed.tpm
> > 
> > Or, to seal the key with the raw sealed key:
> > 
> > $ sudo grub-protect --action=add \
> >                      --protector=tpm2 \
> >                      --tpm2-pcrs=0,2,4,7,9 \
> >                      --tpm2-keyfile=luks-key \
> >                      --tpm2-outfile=/boot/efi/efi/grub/sealed.key
> > 
> 
> > +static grub_err_t
> > +protect_read_file (const char *filepath, void **buffer, size_t 
> > *buffer_size)
> > +{
> > +  grub_err_t err;
> > +  FILE *f;
> > +  long len;
> > +  void *buf;
> > +
> > +  f = fopen (filepath, "rb");
> > +  if (f == NULL)
> 
> An error message should be either printed here or the caller should print
> out an error. Otherwise no error message appears at all.
> 
Right, the user needs to know what goes wrong with file reading.
I'll add messages for every error in this function.


> > +    return GRUB_ERR_FILE_NOT_FOUND;
> > +
> > +  if (fseek (f, 0, SEEK_END))
> > +    {
> > +       err = GRUB_ERR_FILE_READ_ERROR;
> > +       goto exit1;
> > +    }
> > +
> > +  len = ftell (f);
> > +  if (len <= 0)
> > +    {
> > +       err = GRUB_ERR_FILE_READ_ERROR;
> > +       goto exit1;
> > +    }
> > +
> > +  rewind (f);
> > +
> > +  buf = grub_malloc (len);
> > +  if (buf == NULL)
> > +    {
> > +       err = GRUB_ERR_OUT_OF_MEMORY;
> > +       goto exit1;
> > +    }
> > +
> > +  if (fread (buf, len, 1, f) != 1)
> > +    {
> > +       err = GRUB_ERR_FILE_READ_ERROR;
> > +       goto exit2;
> > +    }
> > +
> > +  *buffer = buf;
> > +  *buffer_size = len;
> > +
> > +  buf = NULL;
> > +  err = GRUB_ERR_NONE;
> > +
> > + exit2:
> > +  grub_free (buf);
> > +
> > + exit1:
> 
> probably also print an error message here that something with the file went
> wrong.
> 
> > +  fclose (f);
> > +
> > +  return err;
> > +}
> > +
> > +static grub_err_t
> > +protect_write_file (const char *filepath, void *buffer, size_t buffer_size)
> > +{
> > +  grub_err_t err;
> > +  FILE *f;
> > +
> > +  f = fopen (filepath, "wb");
> > +  if (f == NULL)
> 
> Here the caller prints out err. Good.
> 
> > +    return GRUB_ERR_FILE_NOT_FOUND;
> > +
> > +  if (fwrite (buffer, buffer_size, 1, f) != 1)
> > +  {
> > +    err = GRUB_ERR_WRITE_ERROR;
> > +    goto exit;
> > +  }
> > +
> > +  err = GRUB_ERR_NONE;
> > +
> > + exit:
> > +  fclose (f);
> > +
> > +  return err;
> > +}
> > +
> > +grub_err_t
> > +grub_tcg2_get_max_output_size (grub_size_t *size)
> > +{
> > +  if (size == NULL)
> > +    return GRUB_ERR_BAD_ARGUMENT;
> > +
> > +  *size = GRUB_TPM2_BUFFER_CAPACITY;
> > +
> > +  return GRUB_ERR_NONE;
> > +}
> > +
> > +grub_err_t
> > +grub_tcg2_submit_command (grub_size_t input_size, grub_uint8_t *input,
> > +                     grub_size_t output_size, grub_uint8_t *output)
> > +{
> > +  static const grub_size_t header_size = sizeof (grub_uint16_t) +
> > +                                    (2 * sizeof(grub_uint32_t));
> > +
> > +  if (write (protector_tpm2_fd, input, input_size) != input_size)
> 
> Also here ...
> 
> > +    return GRUB_ERR_BAD_DEVICE;
> > +
> > +  if (read (protector_tpm2_fd, output, output_size) < header_size)
> 
> ... and here since the (single) caller does not print an error.
> 
I'll add error messages for write()/read() here.

Thanks,

Gary Lin

> > +    return GRUB_ERR_BAD_DEVICE;
> > +
> > +  return GRUB_ERR_NONE;
> > +}
> > +

_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to