Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for OVMF hashes #11

Merged
merged 1 commit into from
Mar 28, 2023
Merged

Add support for OVMF hashes #11

merged 1 commit into from
Mar 28, 2023

Conversation

agraf
Copy link

@agraf agraf commented Mar 24, 2023

Some times we may not want to have to keep the full OVMF binary handy when we try to validate a measurement. Most of the data we extract out of the OVMF binary is static, except for its actual hashes.

So let's introduce a new mode that generates a precalculated launch digest that contains the SNP ld hash at the point where we fully ingested OVMF's contents:

$ sev-snp-measure --mode ovmf-hash --ovmf OVMF.fd
cab7e[...]

In addition, add a new optional parameter that a user can then use to consume the hash instead of recalculating it from their OVMF binary at hand:

$ sev-snp-measure --mode snp --vcpus=1 --vcpu-type=EPYC-v4 \
                  --ovmf=OVMF.fd.old --ovmf-hash cab7e[...]
d5269[...]

With this in place, users no longer need to copy full OVMF binaries around. Instead, for almost all SEV-SNP capable OVMF binaries in existence today, we can merely share their hash values and are still able to validate VM measurements.

@dubek dubek added the enhancement New feature or request label Mar 26, 2023
Copy link
Member

@dubek dubek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @agraf for your contribution! I think it's a good idea to allow easily generating launch digests for several OVMFs without holding the full OVMF binaries.

See few comments below:

README.md Outdated
@@ -56,6 +57,7 @@ optional arguments:
--append CMDLINE Kernel command line to calculate hash from (use with --kernel)
--output-format {hex,base64}
Measurement output format
--ovmf-hash HASH Precalculated hash of the OVMF binary
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this should be --snp-ovmf-hash because it's only working for SNP guests?

Copy link
Author

@agraf agraf Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a great point, will change here and in mode.

README.md Outdated
## Precalculated OVMF hashes

In situations where only minor OVMF changes happen, you may not want to copy the full OVMF binary to the validation system. In these situations, you can use an OVMF hash.
To generate a hash, use the `--gen-ovmf-hash` parameter:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you mention here --gen-ovmf-hash but I don't see it anywhere else.

Copy link
Author

@agraf agraf Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had --gen-ovmf-hash as a special argument instead of --mode=ovmf-hash. But while writing the README and seeing how clumsy everything became, I figured I'd fold it in with --mode.

This is a leftover from the original version. I'll change it :)

@@ -41,8 +41,13 @@ def main() -> int:
parser.add_argument('--append', metavar='CMDLINE',
help='Kernel command line to calculate hash from (use with --kernel)')
parser.add_argument('--output-format', choices=['hex', 'base64'], help='Measurement output format', default='hex')
parser.add_argument('--ovmf-hash', metavar='HASH', help='Precalculated hash of the OVMF binary')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
parser.add_argument('--ovmf-hash', metavar='HASH', help='Precalculated hash of the OVMF binary')
parser.add_argument('--ovmf-hash', metavar='HASH', help='Precalculated hash of the OVMF binary (hex string)')

@@ -23,7 +23,7 @@ def main() -> int:
description='Calculate AMD SEV/SEV-ES/SEV-SNP guest launch measurement')
parser.add_argument('--version', action='version', version=f'%(prog)s {VERSION}')
parser.add_argument('-v', '--verbose', action='store_true')
parser.add_argument('--mode', choices=['sev', 'seves', 'snp'], help='Guest mode', required=True)
parser.add_argument('--mode', choices=['sev', 'seves', 'snp', 'ovmf-hash'], help='Guest mode', required=True)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit strange to add this to the --mode argument. What do you think about introducing a new argument --only-produce-ovmf-hash , and in that case, verify that mode is snp ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had that originally and found it a lot more clumsy, because now you have a mandatory mode parameter which isn't actually mandatory because you're really only generating half the digest.

What if we change this to snp-ovmf-hash and change the description of the feature in a way that explains SNP digest generation as a 2 step process. This mode only executes the first step. The snp mode can ingest the first step as input.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even better: While changing it accordingly, I realized we can call the mode snp:ovmf-hash. That makes it obvious that we're executing part of the snp hash calculation.

sevsnpmeasure/guest.py Show resolved Hide resolved
@dubek
Copy link
Member

dubek commented Mar 27, 2023

Also, please run make typecheck - I see some type hints errors:

  make typecheck
  shell: /usr/bin/bash -e {0}
  env:
    pythonLocation: /opt/hostedtoolcache/Python/3.8.16/x64
    LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.8.16/x64/lib
mypy .
sevsnpmeasure/guest.py:18: error: Incompatible default for argument "ovmf_hash_str" (default has type "None", argument has type "str")  [assignment]
sevsnpmeasure/guest.py:18: note: PEP 484 prohibits implicit Optional. Accordingly, mypy has changed its default to no_implicit_optional=True
sevsnpmeasure/guest.py:18: note: Use https://github.com/hauntsaninja/no_implicit_optional to automatically upgrade your codebase
sevsnpmeasure/cli.py:49: error: Return value expected  [return-value]
Found 2 errors in 2 files (checked 12 source files)
make: *** [Makefile:10: typecheck] Error 1
Error: Process completed with exit code 2.

Some times we may not want to have to keep the full OVMF binary handy
when we try to validate a measurement. Most of the data we extract out
of the OVMF binary is static, except for its actual hashes.

So let's introduce a new mode that generates a precalculated launch
digest that contains the SNP ld hash at the point where we fully
ingested OVMF's contents:

  $ sev-snp-measure --mode snp:ovmf-hash --ovmf OVMF.fd
  cab7e[...]

In addition, add a new optional parameter that a user can then use to
consume the hash instead of recalculating it from their OVMF binary at
hand:

  $ sev-snp-measure --mode snp --vcpus=1 --vcpu-type=EPYC-v4 \
                    --ovmf=OVMF.fd.old --snp-ovmf-hash cab7e[...]
  d5269[...]

which is identical to the full calculation with the new OVMF.fd:

  $ sev-snp-measure --mode snp --vcpus=1 --vcpu-type=EPYC-v4 --ovmf=OVMF.fd
  d5269[...]

With this in place, we no longer need to copy full OVMF binaries around.
Instead, for almost all OVMF binaries in existence today, we can merely
share their hash values and are still able to validate the measurement
correctness.

Signed-off-by: Alexander Graf <graf@amazon.com>
@agraf
Copy link
Author

agraf commented Mar 27, 2023

I posted v2 with comments above addressed :)

Copy link
Member

@dubek dubek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great. Thanks for fixing.

@dubek dubek merged commit b6db121 into virtee:main Mar 28, 2023
@dubek
Copy link
Member

dubek commented Apr 13, 2023

Thanks again @agraf . This is now part of release sev-snp-measure 0.0.4 on pypi.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants