Allow accessing raw created/modified FILETIME - #82
Conversation
This is necessary to correctly compute the authenticode hash of an MSI file[0]. While it's technically possible to get the FILETIME back from the SystemTime, it's a lossy operation (a FILETIME that doesn't fit in a SystemTime returns UNIX_TIME). It'd be nicer to just have access to the raw value so we can guarantee we're hashing the correct value. [0]: http://github.com/ralphje/signify/blob/master/signify/authenticode/signed_file/msi.py
|
@mdsteele mind approving CI run? |
francisdb
left a comment
There was a problem hiding this comment.
Thanks, the accessors are a sensible addition. One thing to check before merging, because I think it affects your use case:
Stream timestamps are zeroed by the permissive parser. DirEntry::read_from replaces a non-zero creation/modification time on a stream entry with zero under permissive validation (the default for open), and strict mode rejects such a file (direntry.rs, the two Timestamp::zero() assignments near lines 229 and 239). signify's MSI authenticode hash covers the timestamps of every non-root entry, streams included. So for an MSI whose streams carry timestamps, created_raw()/modified_raw() return 0 rather than the stored value, and the doc comment ("as it is stored in the file") does not hold.
I checked with a file where a storage and a stream both have their FILETIMEs patched to non-zero, opened with CompoundFile::open:
storage: created_raw=0x1d0123456789abc modified_raw=0x1d0fedcba987654
stream: created_raw=0x0 modified_raw=0x0
Suggestion: keep the values as read for streams in permissive mode (or keep raw copies alongside the normalized ones), and add a test along those lines so the raw accessors are covered.
| self.creation_time.to_system_time() | ||
| } | ||
|
|
||
| /// Returns the raw FILETIME value of [`created`], as it is stored in the |
There was a problem hiding this comment.
Unresolved intra-doc link (rustdoc warns no item named \created` in scope); [Entry::created]` resolves.
| self.modified_time.to_system_time() | ||
| } | ||
|
|
||
| /// Returns the raw FILETIME value of [`modified`], as it is stored in the |
There was a problem hiding this comment.
Same here: [Entry::modified].
I'm currently working on a crate verifying authenticode signatures for MSI, and using the CFB crate to parse the MSI files to achieve this.
To verify an MSI signature, it is necessary to access the raw created/modified values, as they are part of the authenticode hash1. While it's technically possible to get the FILETIME back from the SystemTime, it's a lossy operation (a FILETIME that doesn't fit in a SystemTime converts it to SystemTime::UNIX_TIME). It'd be nicer to just have access to the raw value so we can guarantee we're hashing the correct value.
This MR adds two new methods to
Entryto access the raw FILETIME values.Footnotes
http://github.com/ralphje/signify/blob/master/signify/authenticode/signed_file/msi.py#L193-L194 ↩