using openssl ts (https://www.openssl.org/docs/man1.1.0/man1/openssl-ts.html) I can create TS queries, replies, extract tokens from replies and verify tokens (if I have the signing certificate in DER format) of the RFC3161 format as specified here: https://www.ietf.org/rfc/rfc3161.txt
To get a token, I can do:
openssl ts -query -digest 899ba3d9f777e2a74bdd34302bc06cb3f7a46ac1f565ee128f79fd5dab99d68b -sha256 \
| curl -s -H "Content-Type: application/timestamp-query" -H "Accept: application/timestamp-reply" --data-binary @- https://freetsa.org/tsr > response.tsr
openssl ts -reply -in response.tsr -token_out -out token.tk
I can also print the response in human readable form using openssl ts -reply -in response.tsr -text
To verify the token, I need to provide the parameter
-CAfile trusted_certs.pem
The name of the file containing a set of trusted self-signed CA certificates in PEM format.
The file should contain one or more certificates in PEM format.
Question 1:
Why does this only require the trust-anchor (=self-signed) certificate and not the whole chain down to the TSA certificate (or does -verify only work with tokens for which the certificate chain has been included in the token)?
Question 2:
-cert
The TSA is expected to include its signing certificate in the response.
If I specify the -cert parameter in the first openssl call, then token.tk will be longer and also contain the certificate that was used to sign it. How can I extract that certificate from token.tk?
Question 3:
I'm surprised that token.tk gets longer when I request the response to include the certificates (I would have assumed only response.tsr to get longer, not the token itself), since the specification specifies TimeStampToken like so:
   A TimeStampToken is as follows.  It is defined as a ContentInfo
   ([CMS]) and SHALL encapsulate a signed data content type.
   TimeStampToken ::= ContentInfo
     -- contentType is id-signedData ([CMS])
     -- content is SignedData ([CMS])
   The fields of type EncapsulatedContentInfo of the SignedData
   construct have the following meanings:
   eContentType is an object identifier that uniquely specifies the
   content type.  For a time-stamp token it is defined as:
   id-ct-TSTInfo  OBJECT IDENTIFIER ::= { iso(1) member-body(2)
   us(840) rsadsi(113549) pkcs(1) pkcs-9(9) smime(16) ct(1) 4}
   eContent is the content itself, carried as an octet string.
   The eContent SHALL be the DER-encoded value of TSTInfo.
   TSTInfo ::= SEQUENCE  {
   version                      INTEGER  { v1(1) },
   policy                       TSAPolicyId,
   messageImprint               MessageImprint,
     -- MUST have the same value as the similar field in
     -- TimeStampReq
   serialNumber                 INTEGER,
    -- Time-Stamping users MUST be ready to accommodate integers
    -- up to 160 bits.
   genTime                      GeneralizedTime,
   accuracy                     Accuracy                 OPTIONAL,
   ordering                     BOOLEAN             DEFAULT FALSE,
   nonce                        INTEGER                  OPTIONAL,
     -- MUST be present if the similar field was present
     -- in TimeStampReq.  In that case it MUST have the same value.
   tsa                          [0] GeneralName          OPTIONAL,
   extensions                   [1] IMPLICIT Extensions   OPTIONAL  }
So, where is the signing certificate stored? is it an extension? or is it part of the ContentType identifier?
Question 4:
If I did specify the -cert parameter, how can I extract a file token_stripped.tk from token.tk, so that token_stripped.tk is the same as if I would have created the request without the -cert argument?
Question 5:
How can I extract the PKIStatus (as specified in the linked specification) from response.tsr (optimally without first converting it to human readable form)?
                        
Answering my own questions:
It actually does require it, but if the token already contains the entire trust chain embedded, then it's not needed. Otherwise it must be provided using the -untrusted argument
The following call extracts the embedded certificates:
TstInfo actually remains the same length, but the timestamp token is not the TstInfo but the wrapping CMS ContentInfo, and the certificates are (conforming to specification) embedded as a signed attribute in that ContentInfo object.
Since the certificates are embedded in a signed attribute and not an unsigned, it's not possible to generate a valid stripped token from one that contains the certificate chain.
i didn't find a way other than parsing the human readable form using openssl cli