On 11/09/2015 12:30, Michael Heide wrote: > Hi, > I'm using OpenSSL to verify a (proprietary?) timestamp in Microsoft Authenticode via PKCS7_verify() (in pk7_smime.c). According to my (initial) research, Microsoft Authenticode uses two forms of timestamp unauthenticated attributes Here is an excerpt from my draft specification so far: ... 7. Authenticode signatures SHOULD include a counterSignature attribute from a timestamping authority. 8. If there is a valid counterSignature from a timestamping authority and this counterSignature passes validation at the time when the countersigned signature is checked, and the countersigned signature itself was not made with a certificate with the KpLifetimeSigning extended key usage (OID 1.3.6.1.4.1.311.10.3.13), THEN the validity of the countersigned signature (and in particular the applicable certificates) SHOULD be checked as of the time specified by the Authenticated signingTime attribute found in the timestamping countersignature (not any other signingTime attributes found elsewhere in the overall signature structure). 9. If there is no valid counterSignature from a timestamping authority or that countersignature does not pass validation or KpLifetimeSigning was speficied, the signature SHOULD be checked as of the time when it is being checked. The failure or omission of the counterSignature does not invalidate the signature itself (but may still cause it to be invalid due to certificate expiration or revocation). 10. Authenticode signatures SHOULD include a signingTime authenticated attribute (which will usually differ from that attribute in a counterSignature). Recipients should treat this as for information only. ... 2.3 AuthentiCode Timestamp countersignature format ================================================== AuthentiCode signatures typically include a counter signature from a timestamping authority confirming that the signature was made on or prior to a specific time. This is done using a counterSignature unauthenticated attribute of one of the following forms. 2.3.1 RFC2985 form Timestamp countersignature Attribute ======================================================= This is a counter signature exactly as described in RFC2985 section 5.3.6 (OID 1.2.840.113549.1.9.6) with the following additional constraints: - The countersigning certificate MUST specify the timestamping extended key usage (OID 1.3.6.1.5.5.7.3.8) - The countersigning SignerInfo MUST include a signingTime attribute (as defined in RFC2985 section 5.3.3, OID 1.2.840.113549.1.9.5) 2.3.2 RFC3161 form Timestamp countersignature Attribute ======================================================= rFC3161CounterSign = 1.3.6.1.4.1.311.3.3.1 RFC3161CounterSign ::= TimeStampToken -- See RFC3161 The TimeStampToken must specify a messageImprint computed over the content octets of the encryptedDigest field in the SignerInfo having the attribute. This is identical to the SignatureTimeStampToken attribute specified in RFC3161 Appendix A, except that the OID differs. This form is understood only by those Microsoft validation programs that support SHA-2 or later hash algorithms. Therefore AuthentiCode signatures using the SHA-1 hash algorithm SHOULD use the RFC2985 timestamp countersignature format. AuthentiCode signatures not inside an SpcAdditionalSignatures attribute and made using the SHA-1 or MD5 hash algorithm SHOULD AVOID using the RFC3161 timestamp counter signature format. > Those Timestamps are inside a PKCS7 SignerInfo Structure (OpenSSL type PKCS7_SIGNER_INFO). I put those inside a PKCS7 to be able to use PKCS7_verify(). > Most of them are verified fine. In most cases the encryptedDigest structure inside (pkcs7_signer_info_st->enc_digest) corresponds to an OpenSSL type X509_SIG after decryption, which is an ASN.1 encoded Identifier+Hash (sha1,sha256,...). OpenSSL can parse them and use the hash aka message digest inside. > But sometimes there is only the plain hash (sha1 usually) inside the decrypted "encryptedDigest". OpenSSL doesn't detect this. int_rsa_verify() simply tries to decode it via d2i_X509_SIG() which fails. I have not encountered this before, which signing authority, AlgorithmIdentifier and year (first digits of timestamp) did you see this with? Have you considered the possibility that this may be an ISO/IEC 9796-1 or -2 signature (an old format broken in 1999 for 9796-1 and for 9796-2/MD5 and in 2009 for 9796-2/SHA-1)? Or if neither of those ancient specs match that format, it might besome other equally weak system, especially because Authenticode-compatible timestamp authorities are the perfect victims of chosen-message attacks such as those against ISO 9796-1/-2. > The solution is simple. If there's only a hash inside, then after decryption and removing the rsa-padding the resulting structure has exactly the size of the expected hash (-> use the hash for comparison). In all other cases the decrypted ASN.1 structure must be bigger than the hash (including headers). This test is simple and fast, at least if it fails in the normal case. > I've patched OpenSSL and it works. See Attachment. > I don't think this is a bug inside OpenSSL. In fact, rfc2315 states the encrypted digest has to be a DigestInfo structure: > DigestInfo ::= SEQUENCE { > digestAlgorithm DigestAlgorithmIdentifier, > digest Digest } > This corresponds to OpenSSLs X509_SIG. > So I do not report it as a bug. Probably those Authenticode Timestamps are not standards compliant. Or the PKCS7 structure I'm creating around those SignerInfos is wrong/broken/incomplete. Or maybe my approach to use PKCS7_verify() for this is wrong? Thus I would like to share my experiences here. > Nevertheless, if there are no regular cases where i equals m_len in int_rsa_verify(), then it shouldn't do any harm to include those changes in OpenSSL. (with added handling of rm!=NULL which is ignored so far, doesn't get used by RSA_verify(), simple to implement if needed) > Regards > Due to the likely weakness of this scheme, acceptance should be restricted to a very small number of specific signer certificates, and further restricted to specific (claimed) date ranges. Though restricting the claimed date rangewill have very little value, since if that authority signed just a few timestamps requested by an attacker knowing the method published in 1999, that attacker now has the ability to sign anything using any old date as if he was that authority. Enjoy Jakob -- Jakob Bohm, CIO, Partner, WiseMo A/S. http://www.wisemo.com Transformervej 29, 2860 S?borg, Denmark. Direct +45 31 13 16 10 This public discussion message is non-binding and may contain errors. WiseMo - Remote Service Management for PCs, Phones and Embedded