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

Multiple MSI signatures with different algorithms and a MsiDigitalSignatureEx entry #262

Closed
ebourg opened this issue Apr 28, 2023 · 5 comments
Assignees

Comments

@ebourg
Copy link

ebourg commented Apr 28, 2023

While working on MSI file signing in Jsign I've noticed that the metadata hash in the MsiDigitalSignatureEx entry is not verified by Windows (tested on Windows 10 22H2). It could be a simple byte array of zeros, as long as it's prepended to the content hash, the signature is valid. The size isn't event checked to match the size of the hashing algorithm used for signing, if MsiDigitalSignatureEx is 20 bytes long (as produced by SHA-1) and the content is hashed with SHA-256, the signature is also valid.

That's fairly counter-intuitive and I had to pinch myself twice to be convinced this was real. If confirmed on other versions of Windows this means that it's possible to sign a MSI file multiple times with a MsiDigitalSignatureEx entry and different hashing algorithms. So the msi_check_MsiDigitalSignatureEx method could be modified to allow this case.

@mtrojnar
Copy link
Owner

Could you elaborate on the reason you consider this a useful feature?

@ebourg
Copy link
Author

ebourg commented Apr 28, 2023

That's useful for the same reasons users want to sign multiple times other file formats I guess. It also impacts the signature verification, if osslsigncode computes MsiDigitalSignatureEx when verifying the signature, it may see a signature as invalid while Windows consider it valid. In order to replicate the Windows verification process, the existing MsiDigitalSignatureEx entry should be taken as is and not recomputed when verifying.

@mtrojnar
Copy link
Owner

@olszomal Can you take a look? How hard would it be to implement?

@mtrojnar
Copy link
Owner

Bug-for-bug compatibility with Microsoft is not a goal of this project. Depending on missing checks in the current implementation of Windows may backfire when Microsoft decides to fix them.

The check was added in 180a775. @mkrautz: Do you think it's a good idea to remove it?

@olszomal
Copy link
Collaborator

The MsiDigitalSignatureEx hash is used to calculate the DigitalSignature hash. The MsiDigitalSignatureEx hash is verified by Windows when the DigitalSignature hash is verified.

I checked whether Windows signtool verifies the MsiDigitalSignatureEx hash.

  1. Sign a MSI file with adding a MsiDigitalSignatureEx section.
osslsigncode sign -certs cert.pem -key key.pem -in unsigned.msi -out signed.msi -add-msi-dse -h sha256
signtool verify /pa /all /v signed.msi

Verifying: signed.msi

Signature Index: 0 (Primary Signature)
Hash of file (sha256): BC5BA32208EE8EAD9F826E476CB53A993F50C0C9023DEA2766E6D9E8791DA4F0

...
Successfully verified: signed.msi

Number of signatures successfully Verified: 1
Number of warnings: 0
Number of errors: 0
osslsigncode.exe verify -in signed.msi -CAfile CACert.pem
Signature Index: 0  (Primary Signature)
Message digest algorithm         : SHA256
Current MsiDigitalSignatureEx    : 6DD4B3D6652409967185FB5BB4A912EAC4FD2FF608552B55C2EE7C0E574B06F5
Calculated MsiDigitalSignatureEx : 6DD4B3D6652409967185FB5BB4A912EAC4FD2FF608552B55C2EE7C0E574B06F5
Current DigitalSignature         : BC5BA32208EE8EAD9F826E476CB53A993F50C0C9023DEA2766E6D9E8791DA4F0
Calculated DigitalSignature      : BC5BA32208EE8EAD9F826E476CB53A993F50C0C9023DEA2766E6D9E8791DA4F0
Calculated message digest        : D43F071C332EAFD8C4C978804D9D62C3CCC3A15392B0520FDC34E3F9AFD47A8F
(...)
Signature verification: ok

Number of verified signatures: 1
Succeeded
  1. Add a nested signature with a different message digest algorithm SHA512 than what exists in the MSI file already SHA256.
    I'm using experimental functionality osslsigncode here.
osslsigncode sign -certs cert.pem -key key.pem -in signed.msi -out nested.msi -add-msi-dse -h sha512 -nest

The initial signature is corrupted,
Windows Error Code: 0x80096010 TRUST_E_BAD_DIGEST

signtool verify /pa /all /v nested.msi

Verifying: nested.msi

Signature Index: 0 (Primary Signature)
Hash of file (sha256): BC5BA32208EE8EAD9F826E476CB53A993F50C0C9023DEA2766E6D9E8791DA4F0
(...)
SignTool Error: WinVerifyTrust returned error: 0x80096010
        The digital signature of the object did not verify.

Signature Index: 1
Hash of file (sha512): 1CEBE0B2A10EE8352BEA5BF8EB77D6275F71B919DAE451BC98E65C8CD4DD90C8B86E9CFF0080C1BC08B6A869A95A870ED030F343EB1E629BA7997C8125FE0B2C
(...)

Number of signatures successfully Verified: 1
Number of warnings: 0
Number of errors: 1
osslsigncode.exe verify -in nested.msi -CAfile CACert.pem

Signature Index: 0  (Primary Signature)

Message digest algorithm         : SHA256
Current MsiDigitalSignatureEx    : A758BA0245EAD06BF3E1BA7A24B85B65C7D6814548295CAE4567CA003981B20A9DF96DF49489E5DEFDDA60E0B78A220067F2D7F02A025A8A57EAE8AC8AFA4A8F
Calculated MsiDigitalSignatureEx : 6DD4B3D6652409967185FB5BB4A912EAC4FD2FF608552B55C2EE7C0E574B06F5 ... MISMATCH!!!
Current DigitalSignature         : BC5BA32208EE8EAD9F826E476CB53A993F50C0C9023DEA2766E6D9E8791DA4F0
Calculated DigitalSignature      : BC5BA32208EE8EAD9F826E476CB53A993F50C0C9023DEA2766E6D9E8791DA4F0
Calculated message digest        : 2213CDDEEB9B687742C7CF3EEB8582C8A5311578E25AA7942059AE2BA2039576

Signature verification: failed


Signature Index: 1

Message digest algorithm         : SHA512
Current MsiDigitalSignatureEx    : A758BA0245EAD06BF3E1BA7A24B85B65C7D6814548295CAE4567CA003981B20A9DF96DF49489E5DEFDDA60E0B78A220067F2D7F02A025A8A57EAE8AC8AFA4A8F
Calculated MsiDigitalSignatureEx : A758BA0245EAD06BF3E1BA7A24B85B65C7D6814548295CAE4567CA003981B20A9DF96DF49489E5DEFDDA60E0B78A220067F2D7F02A025A8A57EAE8AC8AFA4A8F
Current DigitalSignature         : 1CEBE0B2A10EE8352BEA5BF8EB77D6275F71B919DAE451BC98E65C8CD4DD90C8B86E9CFF0080C1BC08B6A869A95A870ED030F343EB1E629BA7997C8125FE0B2C
Calculated DigitalSignature      : 1CEBE0B2A10EE8352BEA5BF8EB77D6275F71B919DAE451BC98E65C8CD4DD90C8B86E9CFF0080C1BC08B6A869A95A870ED030F343EB1E629BA7997C8125FE0B2C
Calculated message digest        : CDB20359ECC4D97C03E491C79618F8B6920E7E1482F18C53CEEA6C33AF8D69BAAC43373E02A18AAB73554D19099FAC477ADED068DFC8839C6F766A974A640BC0
(...)

Signature verification: ok

Number of verified signatures: 2
Succeeded

These DigitalSignatures can be found in the parsed PKCS#7 signature:

osslsigncode extract-signature -in nested.msi -out signature.der
openssl asn1parse -i -inform der -in signature.der
(...)
   43:d=3  hl=2 l= 119 cons:    SEQUENCE
   45:d=4  hl=2 l=  10 prim:     OBJECT            :1.3.6.1.4.1.311.2.1.4
   57:d=4  hl=2 l= 105 cons:     cont [ 0 ]
   59:d=5  hl=2 l= 103 cons:      SEQUENCE
   61:d=6  hl=2 l=  50 cons:       SEQUENCE
   63:d=7  hl=2 l=  10 prim:        OBJECT            :1.3.6.1.4.1.311.2.1.30
   75:d=7  hl=2 l=  36 cons:        SEQUENCE
   77:d=8  hl=2 l=   1 prim:         INTEGER           :01
   80:d=8  hl=2 l=  16 prim:         OCTET STRING      [HEX DUMP]:F1100C0000000000C000000000000046
   98:d=8  hl=2 l=   1 prim:         INTEGER           :00
  101:d=8  hl=2 l=   1 prim:         INTEGER           :00
  104:d=8  hl=2 l=   1 prim:         INTEGER           :00
  107:d=8  hl=2 l=   1 prim:         INTEGER           :00
  110:d=8  hl=2 l=   1 prim:         INTEGER           :00
  113:d=6  hl=2 l=  49 cons:       SEQUENCE
  115:d=7  hl=2 l=  13 cons:        SEQUENCE
  117:d=8  hl=2 l=   9 prim:         OBJECT            :sha256
  128:d=8  hl=2 l=   0 prim:         NULL
  130:d=7  hl=2 l=  32 prim:        OCTET STRING      [HEX DUMP]:BC5BA32208EE8EAD9F826E476CB53A993F50C0C9023DEA2766E6D9E8791DA4F0
(...)
 2751:d=11 hl=3 l= 153 cons:            SEQUENCE
 2754:d=12 hl=2 l=  10 prim:             OBJECT            :1.3.6.1.4.1.311.2.1.4
 2766:d=12 hl=3 l= 138 cons:             cont [ 0 ]
 2769:d=13 hl=3 l= 135 cons:              SEQUENCE
 2772:d=14 hl=2 l=  50 cons:               SEQUENCE
 2774:d=15 hl=2 l=  10 prim:                OBJECT            :1.3.6.1.4.1.311.2.1.30
 2786:d=15 hl=2 l=  36 cons:                SEQUENCE
 2788:d=16 hl=2 l=   1 prim:                 INTEGER           :01
 2791:d=16 hl=2 l=  16 prim:                 OCTET STRING      [HEX DUMP]:F1100C0000000000C000000000000046
 2809:d=16 hl=2 l=   1 prim:                 INTEGER           :00
 2812:d=16 hl=2 l=   1 prim:                 INTEGER           :00
 2815:d=16 hl=2 l=   1 prim:                 INTEGER           :00
 2818:d=16 hl=2 l=   1 prim:                 INTEGER           :00
 2821:d=16 hl=2 l=   1 prim:                 INTEGER           :00
 2824:d=14 hl=2 l=  81 cons:               SEQUENCE
 2826:d=15 hl=2 l=  13 cons:                SEQUENCE
 2828:d=16 hl=2 l=   9 prim:                 OBJECT            :sha512
 2839:d=16 hl=2 l=   0 prim:                 NULL
 2841:d=15 hl=2 l=  64 prim:                OCTET STRING      [HEX DUMP]:1CEBE0B2A10EE8352BEA5BF8EB77D6275F71B919DAE451BC98E65C8CD4DD90C8B86E9CFF0080C1BC08B6A869A95A870ED030F343EB1E629BA7997C8125FE0B2C
(...)

The initial signature is corrupted in the following cases:

  • When a nested signature is added with a different message digest algorithm than what already exists in the MSI file,
  • When a nested signature is added with the -add-msi-dse parameter, but the initial signature does not contain MsiDigitalSignatureEx,
  • When a nested signature is added without the -add-msi-dse parameter, but the initial signature contains MsiDigitalSignatureEx."

A corrupted signature is useless, so the file should be signed again instead of adding a nested signature.

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

No branches or pull requests

3 participants