-
Notifications
You must be signed in to change notification settings - Fork 55
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 caculating kernel eventlog digist when using OVMF+QEMU #655
Conversation
@jiazhang0 , would you please review this patch? |
@jiazhang0 do you have time to review this patch? |
|
||
// Refer to https://learn.microsoft.com/en-us/windows/win32/debug/pe-format, the NumberOfSections' offset is 2 | ||
let pe_addr = | ||
((buf[IMAGE_PE_ADDR + 1] as u16) << 8) | (buf[IMAGE_PE_ADDR] as u16 + PE_SIGNATURE_SIZE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This calculation confused me. This field you're grabbing seems to be e_lfanew
. I'm having trouble finding its size. Do you have a link? It may actually be 32 bits (e.g. here or here), but you're taking 16 bits. (Maybe in practice it's only ever 16 bits?) Also, I wasn't sure why you added PE_SIGNATURE_SIZE
to this. Don't you just want the value at 0x3c?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your correction!
- It should be 32 bits, I've modified it.
- Here the link for coff-file-header: https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#signature-image-only
I want to get the address of coff-file-header and it starts atpe_addr
+PE_SIGNATURE_SIZE
. The variables should be renamed, and I've modified it.
6532fe5
to
3d709bd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall lgtm. btw, if links to the related ovmf and qemu repo are given it would be better
Ok(hex::encode(res)) | ||
} | ||
|
||
fn get_image_regions(buf: Vec<u8>) -> (usize, Vec<usize>, Vec<usize>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fn get_image_regions(buf: Vec<u8>) -> (usize, Vec<usize>, Vec<usize>) { | |
fn get_image_regions(buf: &[u8]) -> (usize, Vec<usize>, Vec<usize>) { |
Use &[u8]
than Vec<u8>
could help to avoid extra memory copy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for your suggestions!
I've added the link and replaced Vec<u8>
with &[u8]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cloned the code from https://github.com/tianocore/edk2-staging/tree/2024-tdvf-ww01.4/OvmfPkg. To build TDVF there are two ways in the document, which one do I need to use?
Also, could you help to give some guides to build the qemu of the intended version? I'd like to do some test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I am not familiar with boot things. Is the kernel vmlinuz
(compressed) specified by qemu, and the TDVF will uncompress and then boot?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To build TDVF there are two ways in the document, which one do I need to use?
Config-B is better, it will extend eventlog to the RTMR or TPM.
could you help to give some guides to build the qemu of the intended version?
I think you can follow the qemu wiki, the latest qemu version should support TDVF. My version is v7.2.0
Is the kernel vmlinuz (compressed) specified by qemu, and the TDVF will uncompress and then boot?
For this question, to be honest, I'm not an expert :(
I think the kernel vmlinuz
may be uncompressed by qemu, TDVF just load kernel from qemu and boot. I can do more research and investigation to figure it out :) .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I use qemu from https://github.com/qemu/qemu.git with tag v7.2.0
and tdvf suggested by you. When I run
qemu-system-x86_64 -machine confidential-guest-support=tdx0 \
-object tdx-guest,id=tdx0 \
-drive if=pflash,format=raw,unit=0,file=./edk2-staging/Build/IntelTdx/DEBUG_GCC5/FV/OVMF_CODE.fd \
-drive if=pflash,format=raw,unit=1,file=./edk2-staging/Build/IntelTdx/DEBUG_GCC5/FV/OVMF_VARS.fd
Error raised
qemu-system-x86_64: -object tdx-guest,id=tdx0: Parameter 'qom-type' does not accept value 'tdx-guest'
What should I do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @Xynnn007 , I got the message that the qemu in my test env was supplied from internel linux os team and BKC team, and the qemu from https://github.com/qemu/qemu.git don't have tdx-guest support.
Link for qemu-tdx: https://github.com/intel/qemu-tdx/tree/tdx-qemu-upstream
Link for qemu-td-partitioning: https://github.com/intel/qemu-td-partitioning (Note: the qemu-bkc in readme is private repo)
You can get support from above link.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @OuyangHang33 . I tested locally with the qemu and tdvf with the following command
./qemu-system-x86_64 \
-machine confidential-guest-support=tdx0 \
-object tdx-guest,id=tdx0,sept-ve-disable=off \
-drive if=pflash,format=raw,unit=0,file=.../edk2-staging/Build/IntelTdx/DEBUG_GCC5/FV/OVMF_CODE.fd \
-drive if=pflash,format=raw,unit=1,file=.../edk2-staging/Build/IntelTdx/DEBUG_GCC5/FV/OVMF_VARS.fd
and the result is
qemu-system-x86_64: ../system/vl.c:2684: qemu_machine_creation_done: Assertion `machine->cgs->ready' failed.
Aborted (core dumped)
Is there anything wrong?
Also, if I use CoCo/Kata's tdx-qemu to run this firmware, I met the error on containerd side
qemu-system-x86_64-tdx-experimental: TDVF metadata doesn't specify TD_HOB location.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you test with the TDX supported system? Because I got a training this afternoon, I will try your command and tdx-qemu on my side later and give the result before tomorrow evening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It is on tdx machine.
thanks! take your time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @OuyangHang33 for the previous response. Two other doubts below.
// SizeOfRawData Offset: 16 Size:4 | ||
// PointerToRawData Offset: 20 Size:4 | ||
// SizeOfSection Size:40 | ||
let mut p = IMGAE_HEADERS_ADDR + 8; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this the right way to find the start of the Section Table? From your reference link:
the location of the section table is determined by calculating the location of the first byte after the headers. Make sure to use the size of the optional header as specified in the file header.
So I'm assuming you need to grab the SizeOfOptionalHeader
described here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, I have corrected. It's better to find the start of the Section Table by:
p = coff_file_header_addr + coff_file_header_size + optional_header_size
.
| ((buf[IMAGE_PE_OFFSET + 2] as u32) << 16) | ||
| ((buf[IMAGE_PE_OFFSET + 1] as u32) << 8) | ||
| (buf[IMAGE_PE_OFFSET] as u32) + PE_SIGNATURE_SIZE; | ||
let number_of_pecoff_entry = buf[coff_file_header_offset as usize + 2]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The spec indicates this field is 2 bytes. I'm referring to NumberOfSections
here. That said, it also reads: "Note that the Windows loader limits the number of sections to 96." So, maybe you're fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It's better to get 2 bytes here. Have corrected.
buf[0x228] = 0x00; | ||
buf[0x229] = 0x00; | ||
buf[0x22A] = 0x02; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a stl_p()
in https://github.com/qemu/qemu/blob/f48c205fb42be48e2e47b7e1cd9a2802e5ca17b0/hw/i386/x86.c#L962C9-L962C14 which means the dst length is 4 bytes (uint32_t
) due to underlying definition https://github.com/qemu/qemu/blob/f48c205fb42be48e2e47b7e1cd9a2802e5ca17b0/include/qemu/bswap.h#L325
Thus we might need to set one more byte here? s.t.
buf[0x22B] = 0x00;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reasonable, I will set one more byte here.
Thanks @OuyangHang33! One final doubt, because I don't have enough context to understand your Should you be predicating any of those byte assignments based on a Hope that makes sense. My intuition for this question is that the digest will be wrong whenever the protocol version affects these cases. |
Hi @portersrc, based on this 1.2. The Real-Mode Kernel Header, we know that if
The input kernel protocol version should be 2.06+ (over 0x206). I've added the Note in README and check in code. |
e3e688e
to
92fa852
Compare
Signed-off-by: OuyangHang33 <[email protected]>
Thank you @portersrc @Xynnn007 ! |
Thanks. Let me do a test to check if it is ok now. Once finished I will add an approve to this PR. Sorry for my busy time, I promise it will be ok until the end of the next week |
Thanks for fielding all my questions; yeah looks good to me! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great. With great help of @arronwy I test it successfully
$ cargo run -p td-shim-tools --bin td-payload-reference-calculator -- kernel -q --kernel bzImage_6.6
warning: unused imports: `PKCS1`, `PSS`
--> library/ring/src/rsa/padding.rs:21:13
|
21 | pkcs1::{PKCS1, RSA_PKCS1_SHA256, RSA_PKCS1_SHA384, RSA_PKCS1_SHA512},
| ^^^^^
22 | pss::{PSS, RSA_PSS_SHA256, RSA_PSS_SHA384, RSA_PSS_SHA512},
| ^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: `ring` (lib) generated 1 warning (run `cargo fix --lib -p ring` to apply 1 suggestion)
Finished dev [unoptimized + debuginfo] target(s) in 0.04s
Running `target/debug/td-payload-reference-calculator kernel -q --kernel bzImage_6.6`
ddb0ae763ef79685a2102128325e6a7f765ef3b602ad22c12e13b97d6f1e44d1dbb4e55fef418003ad37125a14a67a65
while the eventlog parser result
Event Entry:
RTMR: 2
Event Type: EV_EFI_BOOT_SERVICES_APPLICATION
Digest Algorithm: TPM_ALG_SHA384
Digest: ddb0ae763ef79685a2102128325e6a7f765ef3b602ad22c12e13b97d6f1e44d1dbb4e55fef418003ad37125a14a67a65
Event Desc: 18e0db790000000080f315010000000000000001000000002a000000000000000403140072f728144ab61e44b8c39ebdd7f893c7040412006b00650072006e0065006c0000007fff0400
Fix: #633
Tested with local bzImage binary and the result is matched with the programe output mentioned in #633 .