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

Fix signature verification, check_download #23

Merged
merged 3 commits into from
Nov 16, 2023

Conversation

dongsupark
Copy link
Member

@dongsupark dongsupark commented Oct 30, 2023

In update-format-crau, we should check error from verify_rsa_pkcs to handle errors correctly.

Fix bugs when reading from File to buffer. We need to first create a BufReader for reading from the buffer, pass that into parsing functions. That would make the code much easier to maintain, instead of passing File itself. Then we can read data without having to first open the file and track read positions.

We need to introduce get_header_data() to read header and data, setting the begining of the stream including the whole data including delta update header as well as manifest. Doing that, signature verification works well.

Also introduce get_data_blob() to read only data without header, manifest.

We need to skip checking for existing downloads, if the file does not exist. Otherwise, check_download will simply fail in the beginning, due to missing files.

@dongsupark dongsupark requested review from wrl and pothos October 30, 2023 15:43
src/bin/download_sysext.rs Outdated Show resolved Hide resolved
@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 09de03e to c589a61 Compare November 3, 2023 09:53
@pothos
Copy link
Member

pothos commented Nov 3, 2023

The command from #13 (comment) still fails with

Error: "unable to verify signature \"oem-ami.gz\""

src/bin/download_sysext.rs Outdated Show resolved Hide resolved
We should check error from verify_rsa_pkcs to handle errors correctly.
// sigmessages.signatures[] has a single element in case of dev update payloads,
// while it could have multiple elements in case of production update payloads.
// For now we assume only dev update payloads are supported.
// Return the first valid signature, iterate into the next slot if invalid.
sigmessage.signatures.iter()
.find_map(|sig|
verify_sig_pubkey(testdata, sig, pubkeyfile)
verify_sig_pubkey(testdata.as_slice(), sig, pubkeyfile)
.map(Vec::into_boxed_slice))
}

Copy link
Member

Choose a reason for hiding this comment

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

Meta comment on the below function signature: What is the meaning of the return type? Could this be changed to Result with an error to be easier to understand and handle for the caller?

Copy link
Member Author

Choose a reason for hiding this comment

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

As I remember, the first version of the code had a full Result type like you say. After a code review, we chose to drop that for simplicity.

Copy link
Member

@pothos pothos Nov 7, 2023

Choose a reason for hiding this comment

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

I don't understand what this returned array means, normally a verification either succeeds or gives an error.
@wrl Do you have a suggestion on how to improve this?

Currently it's:

// parse_signature_data takes a bytes slice for signature and public key file path.
// Return only actual data, without version and special fields.
pub fn parse_signature_data(testdata: &[u8], sigbytes: &[u8], pubkeyfile: &str) -> Option<Box<[u8]>> {

@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from c589a61 to c38ec2a Compare November 7, 2023 16:31
@dongsupark
Copy link
Member Author

The command from #13 (comment) still fails with

Error: "unable to verify signature \"oem-ami.gz\""

Thanks for testing.
Now the signature verification works as expected.

The first issue was a wrong input buffer was being passed for signature verification. Fixed.

After that, the signature verification still did not work. Its main reason was that a signature of a Flatcar sysext image is generated from the whole data, from the beginning of delta update header to manifest and finally the data blob. Therefore in get_data_blobs we should not use header.translate_offset(0), but simply 0.

@pothos
Copy link
Member

pothos commented Nov 7, 2023

Running this I get outdir/oem-ami.gz written but that's still the payload, we need the extracted contents.

@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from c38ec2a to de20c55 Compare November 8, 2023 09:19
@dongsupark
Copy link
Member Author

Running this I get outdir/oem-ami.gz written but that's still the payload, we need the extracted contents.

Fixed.
Now the extracted data blobs are written to outdir/oem-ami.raw.

@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from de20c55 to 1f69b54 Compare November 8, 2023 09:35
src/bin/download_sysext.rs Outdated Show resolved Hide resolved
@pothos
Copy link
Member

pothos commented Nov 8, 2023

Fixed.
Now the extracted data blobs are written to outdir/oem-ami.raw.

Something is wrong, please let the program check that the output matches the hash of new_partition_info.

For reference you can compare with the output of the bash decode_payload script which does things right.

PROTOPATH=src/update_engine/ ./decode_payload ~/flatcar/scripts/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-au-key/files/official-v2.pub.pem /var/tmp/oem-ami.gz /var/tmp/oem-ami.raw

@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 1f69b54 to b9c3665 Compare November 8, 2023 17:09
@dongsupark
Copy link
Member Author

Something is wrong, please let the program check that the output matches the hash of new_partition_info.

Done with reimplementing getting header and data parts.

@pothos
Copy link
Member

pothos commented Nov 9, 2023

Done with reimplementing getting header and data parts.

Thanks, that finally gives a working result

src/bin/download_sysext.rs Outdated Show resolved Hide resolved
@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from b9c3665 to 3d8ef7a Compare November 9, 2023 14:28
src/bin/download_sysext.rs Outdated Show resolved Hide resolved
We need to skip checking for existing downloads, if the file does not
exist. Otherwise, check_download will simply fail in the beginning,
due to missing files.
@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 3d8ef7a to 726cf6f Compare November 10, 2023 10:18
@pothos
Copy link
Member

pothos commented Nov 10, 2023

The last changes with the hardcoded tmp path make extraction fail:

code: 18, kind: CrossesDevices, message: "Invalid cross-device link"

@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 726cf6f to 811afa0 Compare November 10, 2023 17:12
@dongsupark
Copy link
Member Author

The last changes with the hardcoded tmp path make extraction fail:

code: 18, kind: CrossesDevices, message: "Invalid cross-device link"

This is now fixed.

@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 811afa0 to 7f58af1 Compare November 10, 2023 18:46
test/crau_verify.rs Outdated Show resolved Hide resolved
@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 7f58af1 to 3a986a7 Compare November 14, 2023 16:27
src/bin/download_sysext.rs Outdated Show resolved Hide resolved
src/bin/download_sysext.rs Outdated Show resolved Hide resolved
Copy link
Member

@pothos pothos left a comment

Choose a reason for hiding this comment

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

I get this error Error: Error { kind: UnexpectedEof, message: "failed to fill whole buffer" }
when running target/debug/download_sysext -p ~/flatcar/scripts/sdk_container/src/third_party/coreos-overlay/coreos-base/coreos-au-key/files/official-v2.pub.pem -m flatcar_production_update.gz -o /var/tmp/outdir/ -i /var/tmp/beta-response-genericsha256
with beta-response-genericsha256:

<?xml version="1.0" encoding="UTF-8"?>
<response protocol="3.0" server="nebraska"><daystart elapsed_seconds="0"></daystart><app appid="e96281a6-d1af-4bde-9a0a-97b76e56dc57" status="ok"><ping status="ok"></ping><updatecheck status="ok"><urls><url codebase="https://update.release.flatcar-linux.net/amd64-usr/3745.1.0/"></url></urls><manifest version="3745.1.0"><packages><package name="flatcar_production_update.gz" hash_sha256="07b07d57e4140675fc008ce59ae37bb976cc78a794a502551eefd712169ea427" hash="wu2kqzo1DdPfjLTKHsILXA/+NQc=" size="387642070" required="true"></package><package name="oem-ami.gz" hash="gwCrRdY+wOMO8xSU5CsvGEHsF4k=" hash_sha256="46a5f66202f89f9ca93b90476466bf8325976749a22aac2550e84cc4e3d61bb7" size="25669804" required="false"></package><package name="oem-azure.gz" hash="j0uFpiFGOGZxEtoQgMIJXFQhMpc=" hash_sha256="2d5d6ef2d61b05aadc41289f42cfbe08e2639717dabc09a3363f7f561d39318a" size="40969473" required="false"></package><package name="oem-qemu.gz" hash="DR/utcV9lnjq8f2+PHRl45Mm+hQ=" hash_sha256="a71ac69e59a66d20d6194db450bdc6bc05b27822eaa8890c6796586739bed0b9" size="2262" required="false"></package><package name="oem-vmware.gz" hash="JIjyTXkB+N7DmihOJP+LreXFyWI=" hash_sha256="38287be053ee9abbd1ea9c755235cf226eeaf30d03c94a8733f499955e4b4c65" size="1794357" required="false"></package></packages><actions><action event="postinstall" sha256="B7B9V+QUBnX8AIzlmuN7uXbMeKeUpQJVHu/XEhaepCc=" DisablePayloadBackoff="true"></action></actions></manifest></updatecheck><event status="ok"></event></app></response>

@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 3a986a7 to 2d602ef Compare November 15, 2023 16:19
@dongsupark
Copy link
Member Author

I get this error Error: Error { kind: UnexpectedEof, message: "failed to fill whole buffer" }

Fixed. freader.seek was needed.

src/bin/download_sysext.rs Outdated Show resolved Hide resolved
src/bin/download_sysext.rs Outdated Show resolved Hide resolved
src/bin/download_sysext.rs Outdated Show resolved Hide resolved
Fix bugs when reading from File to buffer. We need to first create a
BufReader for reading from the buffer, pass that into parsing functions.
That would make the code much easier to maintain, instead of passing
File itself. Then we can read data without having to first open the file
and track read positions.

We need to get length of header and data, reading from the begining of
the stream including the whole data including delta update header as well
as manifest. And pass the length to hash_on_disk to calculate the hash
without having to read the while data into memory. Doing that, signature
verification works well.

Also introduce get_data_blob() to read only data without header,
manifest.
@dongsupark dongsupark force-pushed the dongsu/fix-download-sig branch from 2d602ef to 0088652 Compare November 16, 2023 08:28
@dongsupark
Copy link
Member Author

Done with having seek only once.

Added more comments.

@pothos pothos linked an issue Nov 16, 2023 that may be closed by this pull request
@dongsupark
Copy link
Member Author

Thanks!

@dongsupark dongsupark merged commit 58c7969 into trunk Nov 16, 2023
1 check passed
@dongsupark dongsupark deleted the dongsu/fix-download-sig branch November 16, 2023 11:32
dongsupark added a commit to flatcar/scripts that referenced this pull request Nov 16, 2023
Update ue-rs to 0.1.0-r3, 2023-11-16.
Pulls in flatcar/ue-rs#23 and
flatcar/ue-rs#24.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Verification and reporting
2 participants