I was having trouble with this too. In addition to the other answers, I found a mailing list post that says the following:
Looking at the TS code in OpenSSL, it seems that the peer's
chain is not used in the way one might expect (to help construct
the untrusted portion of the chain). Rather, surprisingly, it
looks like the peer's certificates appear to be used as a "constraint"
on the constructed chain, and verification fails some chain element
was not provided by the peer. I don't know why this is done.
So that means you need to manually construct the full chain. The answer from fred727 has the most important part of the info, but here's a full example.
Assume you have response.tsr
from http://timestamp.digicert.com
. Extract the subject
and issuer
info from the embedded certificates:
openssl ts -reply -in response.tsr -token_out \
| openssl pkcs7 -inform der -print_certs \
| grep 'subject\|issuer'
That gives this output:
subject=C = US, O = "DigiCert, Inc.", CN = DigiCert Timestamp 2021
issuer=C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Assured ID Timestamping CA
subject=C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert SHA2 Assured ID Timestamping CA
issuer=C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Assured ID Root CA
The first certificate is DigiCert Timestamp 2021
and was issued by DigiCert SHA2 Assured ID Timestamping CA
which was issued by DigiCert Assured ID Root CA
. The DigiCert Assured ID Root CA
certificate is part of the OS certificate store (at least on Ubuntu), so you can use the known good root certificate along with the embedded certificates supplied in the timestamping response to build a full chain. As long as you trust the root, you can trust the full chain.
Use fred727's advice to create a partial chain from the embedded certificates.
openssl ts -reply -in response.tsr -token_out \
| openssl pkcs7 -inform der -print_certs \
| sed -n '/-----BEGIN/,/-----END/p' > chain.pem
Then concatenate the well known root with the supplied chain.
cat chain.pem /etc/ssl/certs/DigiCert_Assured_ID_Root_CA.pem > timestamp.digicert.com-full-chain.pem
Now you should be able to use that full chain as the argument to the CAfile
option to verify signatures.