Re: Verifying authenticode signature using openssl API

2014-09-22 Thread Prasad Dabak

Well, I am bit confused here.

I am decrypting the signature using RSA_public_decrypt function passing it a 
public key with RSA_PKCS1_PADDING option.

For primary signature, I get back a 35 byte value which is inclusive of the 
digestAlgorithm. It is in the v1.5 format that you mention about.
For secondary signature, I get back a 20 byte value which matches byte-to-byte 
with the digest (SHA1 hash of the signed attributes si-auth_attr). But it 
doesn't include digestAlgorithm.

I understand that primary and secondary signatures are generated by different computers 
belonging to different companies. However, the fact that the decrypted signature matches 
with the SHA1 hash of the signed attributes makes me believe, that it's probably not a 
different algorithm (DSS/DSA and ECDSA) issue and it doesn't look like PSS 
format issue either.

Thanks.
-Prasad


On Sep 19, 2014, at 10:24 AM, Jakob Bohm jb-open...@wisemo.com wrote:


On 19/09/2014 09:14, Prasad Dabak wrote:
The RFC links helped.
   
I am able to do decrypt the encrypted digest and match it with the
DigestInfo as explained in rfc2315.
DigestInfo ::= SEQUENCE {
digestAlgorithm DigestAlgorithmIdentifier,
digest Digest }
   
Digest ::= OCTET STRING
   
I typically get back 35 byte decrypted digest which matches with 
sequence above.
I am also able to validate counterSignatures in similar fashion.
   
Now I am trying this with various Authenticode executables and one
small issue that I found is: For some authenticode executables, the
counterSignature encryption only considers the bytes of the Digest
OCTET_STRING i.e. it does not consider digestAlgorithm field. Because
of this, the decrypted counterSignature is 20 bytes long (size of sha1
hash) instead of 35 bytes mentioned earlier. It does match with bytes
of the Digest OCTET_STRING.
   
Is this expected behavior? How do I programmatically check this
behavior? If the size of decrypted counterSignature is equal to size
of the hash, assume that digestAlgorithm field is not considered?
   
Decrypting and RSA signature should produce a byte string almost
as long as the RSA key length, e.g.127 bytes for 1024 bits, 255
bytes for 2048 bits etc.

Next step is to check if those 127/255/... bytes are formatted
according to the appropriate portion of PKCS#1, whichspecifies
TWO different formats, the old v1.5 format which is mostly the
DigestAlgorithm OID and the digest packed into a simple ASN.1
structure and then padded, and the new PSS format, where the
hash is combined with a random value using a formula which you
can only reverse if you know what the digest should be.

I suspect you may be encountering both formats, since the
countersignature and the primary signature are generated by
different computers belonging to different companies (the
countersignature is generated by a server owned and run be the CA,
the primary signature is generated by the manufacturer and/or
Symantec).

You also need to consider that other signature algorithms such as
DSS/DSA and ECDSA might be used, as specified in the certificates
used for the signatures.

Note: For RSA signatures, PKCS#1 == RFC3447.

Thanks.
-Prasad
   
   
On Sep 16, 2014, at 10:51 AM, Jakob Bohm jb-open...@wisemo.com   
wrote:
   
On 16/09/2014 12:22, Prasad Dabak wrote:
Hello,
   
I am currently focusing on matching various digests 
that we
talked
about earlier in the thread.
   
1. Computing the hash of the executable (excluding 
the areas as
defined by MS) and matching it with the value stored 
in
spcIndirectData. This is straight forward and 
figured out.
2. Computing the hash of spcIndirectData and 
matching it
with with
messageDigest stored in AuthenticatedAttributes. I
realized that the
sequence and length bytes need to be skipped before
computing the hash
of the spcIndirectData? Is this documented anywhere?
This is specified in the PKCS#7 standard (RFC2315), in 
particular,
PKCS#7 specifies that when there is a non-empty contentInfo 
field
in the PKCS#7 structure, which part of that should be hashed. 
In
this case that contentInfo is a Microsoft-defiend 
spcIndirectData,
but the calculation is unaffected. This should also be built 
in
to the PKCS7 functions (I hope).
3. Computing hash of AuthenticatedAttributes and 
matching it
with

Re: Verifying authenticode signature using openssl API

2014-09-22 Thread Jakob Bohm

Ok, look in the SignerInfo structure of the secondary signature.
 There is a separate field (digestEncryptionAlgorithm) indicating
the OID of the signature algorithm.  Look at this and see if it is
different from the value in the outer signature, and look up the
value online to see what it means.

On 22/09/2014 10:24, Prasad Dabak wrote:

Well, I am bit confused here.

I am decrypting the signature using RSA_public_decrypt function 
passing it a public key with RSA_PKCS1_PADDING option.


For primary signature, I get back a 35 byte value which is inclusive 
of the digestAlgorithm. It is in the v1.5format that you mention about.
For secondary signature, I get back a 20 byte value which matches 
byte-to-byte with the digest (SHA1 hash of the signed attributes 
si-auth_attr). But it doesn't include digestAlgorithm.


I understand that primary and secondary signatures are generated by 
different computers belonging to different companies. However, the 
fact that the decrypted signature matches with the SHA1 hash of the 
signed attributes makes me believe, that it's probably not a different 
algorithm (DSS/DSA and ECDSA) issue and it doesn't look like PSS 
format issue either.


Thanks.
-Prasad


On Sep 19, 2014, at 10:24 AM, Jakob Bohm jb-open...@wisemo.com wrote:


On 19/09/2014 09:14, Prasad Dabak wrote:
The RFC links helped.
   
I am able to do decrypt the encrypted digest and match it 
with the

DigestInfo as explained in rfc2315.
DigestInfo ::= SEQUENCE {
digestAlgorithm DigestAlgorithmIdentifier,
digest Digest }
   
Digest ::= OCTET STRING
   
I typically get back 35 byte decrypted digest which matches 
with sequence above.

I am also able to validate counterSignatures in similar fashion.
   
Now I am trying this with various Authenticode executables 
and one
small issue that I found is: For some authenticode 
executables, the
counterSignature encryption only considers the bytes of the 
Digest
OCTET_STRING i.e. it does not consider digestAlgorithm 
field. Because
of this, the decrypted counterSignature is 20 bytes long 
(size of sha1
hash) instead of 35 bytes mentioned earlier. It does match 
with bytes

of the Digest OCTET_STRING.
   
Is this expected behavior? How do I programmatically check this
behavior? If the size of decrypted counterSignature is equal 
to size
of the hash, assume that digestAlgorithm field is not 
considered?

   
Decrypting and RSA signature should produce a byte string almost
as long as the RSA key length, e.g.127 bytes for 1024 bits, 255
bytes for 2048 bits etc.

Next step is to check if those 127/255/... bytes are formatted
according to the appropriate portion of PKCS#1, whichspecifies
TWO different formats, the old v1.5 format which is mostly the
DigestAlgorithm OID and the digest packed into a simple ASN.1
structure and then padded, and the new PSS format, where the
hash is combined with a random value using a formula which you
can only reverse if you know what the digest should be.

I suspect you may be encountering both formats, since the
countersignature and the primary signature are generated by
different computers belonging to different companies (the
countersignature is generated by a server owned and run be the CA,
the primary signature is generated by the manufacturer and/or
Symantec).

You also need to consider that other signature algorithms such as
DSS/DSA and ECDSA might be used, as specified in the certificates
used for the signatures.

Note: For RSA signatures, PKCS#1 == RFC3447.

Thanks.
-Prasad
   
   
On Sep 16, 2014, at 10:51 AM, Jakob Bohm 
jb-open...@wisemo.com mailto:jb-open...@wisemo.com   wrote:

   
On 16/09/2014 12:22, Prasad Dabak wrote:
Hello,
   
I am currently focusing on matching 
various digests that we

talked
about earlier in the thread.
   
1. Computing the hash of the executable 
(excluding the areas as
defined by MS) and matching it with the 
value stored in
spcIndirectData. This is straight forward 
and figured out.
2. Computing the hash of spcIndirectData 
and matching it

with with
messageDigest stored in 
AuthenticatedAttributes. I

realized that the
sequence and length bytes need to be 
skipped before

computing the hash
of the spcIndirectData? Is this documented 
anywhere?
This is specified in the PKCS#7 standard (RFC2315), 
in particular,
PKCS#7 specifies that when there is a non-empty 
contentInfo field
in the PKCS#7 

Re: Verifying authenticode signature using openssl API

2014-09-16 Thread Prasad Dabak

Hello,

I am currently focusing on matching various digests that we talked about 
earlier in the thread.

1. Computing the hash of the executable (excluding the areas as defined by MS) 
and matching it with the value stored in spcIndirectData. This is straight 
forward and figured out.
2. Computing the hash of spcIndirectData and matching it with with 
messageDigest stored in AuthenticatedAttributes. I realized that the sequence 
and length bytes need to be skipped before computing the hash of the spcIndirectData? Is 
this documented anywhere?
3. Computing hash of AuthenticatedAttributes and matching it with decrypted 
version of encryptedDigest. I am struggling to get this. Which portion of 
AuthenticatedAttributes should be considered for computing the hash? Further 
when I decrypt the encryptedDigest using the signer's public key, I get back a 
256 byte value. This doesn't look like a SHA1 hash like in case (1) and (2). So 
what type of hash it is? Can someone elaborate OR point to documentation that 
elaborates on this?

Thanks.
-Prasad



On Sep 09, 2014, at 10:18 AM, Prasad Dabak pda...@icloud.com wrote:


Thanks Jacob for your response. Very informative indeed!

Thanks
-Prasad

Sent from my iPhone

On 09-Sep-2014, at 10:05 pm, Jakob Bohm jb-open...@wisemo.com 
wrote:
   
On 09/09/2014 09:01, Prasad Dabak wrote:
Thanks Jacob for an elaborate answer. Somehow I never 
received your response to my registered email address, hence delay in responding.
This time I have CC-ed you in addition to the mail list.
I have a few follow-up questions on your response.
   
1. So, encryptedDigest has no relation to the stored 
messageDigest? I thought it's a encrypted version of the messageDigest?
As far as I recall, there is a chain of 4 digests. The first digest
is calculated over the file and is stored in the spcIndirectData. The
second digest is calculated over the spcIndirectData (the contentInfo
of the the PKCS#7 structure) and is stored as messageDigest in the
AuthenticatedAttributes of each PKCS#7 signerInfo. The third hash
is calculated over the AuthenticatedAttributes and is signed to
produce the encryptedDigest in that same signerInfo. All 3 need to
be checked to confirm that the file hash is actually (indirectly)
signed by the encryptedDigest using the public key in the certificate
whose name is listed in the signerInfo.
2. I agree that it's better to do cheaper checks first e.g. I 
am also matching PE checksum stored in the optional header.
Indeed, though that is a very weak checksum (file size plus 16 bit 
TCP/IP
checksum of file). Also it is allowed to be 0 to indicate no checksum
(even if you set the checksum, it might be cleared if an Administrator
adds his own countersignature to all authorized programs on his
computers, aka AppLocker).
3. spcPEImageData is probably relevant only for signing that 
uses page hashes?
I never quite figured out where they store the page hashes. However I
believe the constant semi-empty spcPEImageData with the obsolete

string is the traditional marker to indicate that the signature is for
a PE file, and not e.g. a document file with the same hashed 
bytestream.
   
4. PKCS7_verify is already matching the encryptedDigest, do 
we still need to validate it ourselves?
If it is, I am myself guessing a bit as to what that function does and
does not check. But note that it probably doesn't check the full chain
of 3 message digests, since at least the digest over the file itself is
inside a blob that the PKCS#7 standard has no opinion about.
5. So, basically are are suggesting to look into the subject 
string and see if we can find patterns like /CN=COMPANY-NAME... issuer: 
/C=US/O=SIGNER_NAME? How authoritative it is? I mean can someone else have same 
COMPANY-NAME and PATTERN-NAME in their certificate?
Actually, the subject is a data structure (a hierarchical list of sets
of tagged strings) and the relevant comparison would be to compare 
those
elements that don't change when getting a new certificate from the CA.
It is the CAs responsibility to make sure the don't issue certificates
to the wrong people, and if they make a mistake they are expected to
quickly add the bad certificate to their published CRL, which is why
you need to check the CRL before trusting the certificate. An
additional check is to make sure the CA that issued the intermediary
certificate that issued the COMAPNY-NAME certificate is actually one
of the (few) CAs that COMPANY-NAME is going to buy certificates from.
This protects against fake 

Re: Verifying authenticode signature using openssl API

2014-09-09 Thread Prasad Dabak

Thanks Jacob for an elaborate answer. Somehow I never received your response to 
my registered email address, hence delay in responding.

I have a few follow-up questions on your response.

1. So, encryptedDigest  has no relation to the stored messageDigest? I 
thought it's a encrypted version of the messageDigest?
2. I agree that it's better to do cheaper checks first e.g. I am also matching 
PE checksum stored in the optional header.
3. spcPEImageData is probably relevant only for signing that uses page hashes?
4. PKCS7_verify is already matching the encryptedDigest, do we still need to 
validate it ourselves?
5. So, basically are are suggesting to look into the subject string and see if 
we can find patterns like /CN=COMPANY-NAME... issuer: /C=US/O=SIGNER_NAME? 
How authoritative it is? I mean can someone else have same COMPANY-NAME and 
PATTERN-NAME in their certificate?

In my case, I am the one who is signing the executable using my certificate and a 
cross certificate issued by Microsoft and I want to programmatically ensure 
following things.

1. Code is not tampered since it was signed (matching messageDigest with 
computed hash)
2. Verifying the digital signature (PKCS7_Verify)
3. Confirming that the executable is signed by my company certificate.

I am stuck on part (3) and don't see a clean way apart from matching strings in 
subject field?  If I hard-code the public key in my verification code, I will 
need to update it when I switch to a newer public key?

Thanks.
-Prasad

On Sep 06, 2014, at 09:44 PM, Prasad Dabak pda...@icloud.com wrote:


Hello,

Given a signed Windows portable executable, I want to programmatically verify 
two things using openssl APIs

1. Verify the digital signature.
2. Confirm that the executable is signed by a specific company using that 
company's public key.

It seems that part (1) can be done by parsing the signedData attribute in the 
portable executable, extracting the hashing algorithm and digest stored there, 
re-computing the digest of the executable using the same hashing algorithm and 
match them.

I have following questions.

1. The signData contains messageDigest (unencrypted) and encryptedDigest 
(encrypted). Is it enough to match messgaeDigest with the computed digest? OR 
we also need to decrypt the encryptedDigest using the company public key and 
match that as well?
2. What does PKCS7_Verify exactly do? I looked at 
https://www.openssl.org/docs/crypto/PKCS7_verify.html  and I understand  that 
it verifies certificate chain.  However, it's not clear to me as to what 
exactly it does with respect to signature verification?
3. I am assuming that I require to do both (1) and (2) in order to verify the 
authenticode signature?
4. What is the best way to verify if the executable is signed by specific 
company using that company's public key?

Any inputs will be greatly appreciated!

Thanks.
-Prasad



Re: Verifying authenticode signature using openssl API

2014-09-09 Thread Jakob Bohm

On 09/09/2014 09:01, Prasad Dabak wrote:
Thanks Jacob for an elaborate answer. Somehow I never received your 
response to my registered email address, hence delay in responding.



This time I have CC-ed you in addition to the mail list.

I have a few follow-up questions on your response.

1. So, encryptedDigest  has no relation to the stored 
messageDigest? I thought it's a encrypted version of the messageDigest?

As far as I recall, there is a chain of 4 digests.  The first digest
is calculated over the file and is stored in the spcIndirectData. The
second digest is calculated over the spcIndirectData (the contentInfo
of the the PKCS#7 structure) and is stored as messageDigest in the
AuthenticatedAttributes of each PKCS#7 signerInfo.  The third hash
is calculated over the AuthenticatedAttributes and is signed to
produce the encryptedDigest in that same signerInfo.  All 3 need to
be checked to confirm that the file hash is actually (indirectly)
signed by the encryptedDigest using the public key in the certificate
whose name is listed in the signerInfo.
2. I agree that it's better to do cheaper checks first e.g. I am also 
matching PE checksum stored in the optional header.

Indeed, though that is a very weak checksum (file size plus 16 bit TCP/IP
checksum of file).  Also it is allowed to be 0 to indicate no checksum
(even if you set the checksum, it might be cleared if an Administrator
adds his own countersignature to all authorized programs on his
computers, aka AppLocker).
3. spcPEImageData is probably relevant only for signing that uses page 
hashes?

I never quite figured out where they store the page hashes. However I
believe the constant semi-empty spcPEImageData with the obsolete
string is the traditional marker to indicate that the signature is for
a PE file, and not e.g. a document file with the same hashed bytestream.

4. PKCS7_verify is already matching the encryptedDigest, do we still 
need to validate it ourselves?

If it is, I am myself guessing a bit as to what that function does and
does not check.  But note that it probably doesn't check the full chain
of 3 message digests, since at least the digest over the file itself is
inside a blob that the PKCS#7 standard has no opinion about.
5. So, basically are are suggesting to look into the subject string 
and see if we can find patterns like /CN=COMPANY-NAME... issuer: 
/C=US/O=SIGNER_NAME? How authoritative it is? I mean can someone 
else have same COMPANY-NAME and PATTERN-NAME in their certificate?

Actually, the subject is a data structure (a hierarchical list of sets
of tagged strings) and the relevant comparison would be to compare those
elements that don't change when getting a new certificate from the CA.
It is the CAs responsibility to make sure the don't issue certificates
to the wrong people, and if they make a mistake they are expected to
quickly add the bad certificate to their published CRL, which is why
you need to check the CRL before trusting the certificate.  An
additional check is to make sure the CA that issued the intermediary
certificate that issued the COMAPNY-NAME certificate is actually one
of the (few) CAs that COMPANY-NAME is going to buy certificates from.
  This protects against fake certificates issued by smaller CAs that
you aren't going to use anyway.


In my case, I am the one who is signing the executable using my 
certificate and a cross certificate issued by Microsoft and I want 
to programmatically ensure following things.


1. Code is not tampered since it was signed (matching messageDigest 
with computed hash)

Actually matching digest in spcIndirectData with computed hash. Plus
consistency checks to make sure the signature is actually for a PE file
and was not otherwise doctored.  For instance there should be no bytes
in the file after the end of the signature blob.

2. Verifying the digital signature (PKCS7_Verify)
3. Confirming that the executable is signed by my company certificate.

I am stuck on part (3) and don't see a clean way apart from matching 
strings in subject field?  If I hard-code the public key in my 
verification code, I will need to update it when I switch to a newer 
public key?



Yep, that is why careful matching against various Distinguished Name
fields is needed.



On Sep 06, 2014, at 09:44 PM, Prasad Dabak pda...@icloud.com wrote:


Hello,

Given a signed Windows portable executable, I want to 
programmatically verify two things using openssl APIs


1. Verify the digital signature.
2. Confirm that the executable is signed by a specific company using 
that company's public key.


It seems that part (1) can be done by parsing the signedData 
attribute in the portable executable, extracting the hashing 
algorithm and digest stored there, re-computing the digest of the 
executable using the same hashing algorithm and match them.


I have following questions.

1. The signData contains messageDigest (unencrypted) and 
encryptedDigest (encrypted). Is it enough to match 

Re: Verifying authenticode signature using openssl API

2014-09-09 Thread Prasad Dabak
Thanks Jacob for your response. Very informative indeed!

Thanks
-Prasad

Sent from my iPhone

 On 09-Sep-2014, at 10:05 pm, Jakob Bohm jb-open...@wisemo.com wrote:
 
 On 09/09/2014 09:01, Prasad Dabak wrote:
 Thanks Jacob for an elaborate answer. Somehow I never received your response 
 to my registered email address, hence delay in responding.
 This time I have CC-ed you in addition to the mail list.
 I have a few follow-up questions on your response.
 
 1. So, encryptedDigest  has no relation to the stored messageDigest? I 
 thought it's a encrypted version of the messageDigest?
 As far as I recall, there is a chain of 4 digests.  The first digest
 is calculated over the file and is stored in the spcIndirectData. The
 second digest is calculated over the spcIndirectData (the contentInfo
 of the the PKCS#7 structure) and is stored as messageDigest in the
 AuthenticatedAttributes of each PKCS#7 signerInfo.  The third hash
 is calculated over the AuthenticatedAttributes and is signed to
 produce the encryptedDigest in that same signerInfo.  All 3 need to
 be checked to confirm that the file hash is actually (indirectly)
 signed by the encryptedDigest using the public key in the certificate
 whose name is listed in the signerInfo.
 2. I agree that it's better to do cheaper checks first e.g. I am also 
 matching PE checksum stored in the optional header.
 Indeed, though that is a very weak checksum (file size plus 16 bit TCP/IP
 checksum of file).  Also it is allowed to be 0 to indicate no checksum
 (even if you set the checksum, it might be cleared if an Administrator
 adds his own countersignature to all authorized programs on his
 computers, aka AppLocker).
 3. spcPEImageData is probably relevant only for signing that uses page 
 hashes?
 I never quite figured out where they store the page hashes. However I
 believe the constant semi-empty spcPEImageData with the obsolete
 string is the traditional marker to indicate that the signature is for
 a PE file, and not e.g. a document file with the same hashed bytestream.
 
 4. PKCS7_verify is already matching the encryptedDigest, do we still need to 
 validate it ourselves?
 If it is, I am myself guessing a bit as to what that function does and
 does not check.  But note that it probably doesn't check the full chain
 of 3 message digests, since at least the digest over the file itself is
 inside a blob that the PKCS#7 standard has no opinion about.
 5. So, basically are are suggesting to look into the subject string and see 
 if we can find patterns like /CN=COMPANY-NAME... issuer: 
 /C=US/O=SIGNER_NAME? How authoritative it is? I mean can someone else 
 have same COMPANY-NAME and PATTERN-NAME in their certificate?
 Actually, the subject is a data structure (a hierarchical list of sets
 of tagged strings) and the relevant comparison would be to compare those
 elements that don't change when getting a new certificate from the CA.
 It is the CAs responsibility to make sure the don't issue certificates
 to the wrong people, and if they make a mistake they are expected to
 quickly add the bad certificate to their published CRL, which is why
 you need to check the CRL before trusting the certificate.  An
 additional check is to make sure the CA that issued the intermediary
 certificate that issued the COMAPNY-NAME certificate is actually one
 of the (few) CAs that COMPANY-NAME is going to buy certificates from.
  This protects against fake certificates issued by smaller CAs that
 you aren't going to use anyway.
 
 In my case, I am the one who is signing the executable using my certificate 
 and a cross certificate issued by Microsoft and I want to programmatically 
 ensure following things.
 
 1. Code is not tampered since it was signed (matching messageDigest with 
 computed hash)
 Actually matching digest in spcIndirectData with computed hash. Plus
 consistency checks to make sure the signature is actually for a PE file
 and was not otherwise doctored.  For instance there should be no bytes
 in the file after the end of the signature blob.
 2. Verifying the digital signature (PKCS7_Verify)
 3. Confirming that the executable is signed by my company certificate.
 
 I am stuck on part (3) and don't see a clean way apart from matching strings 
 in subject field?  If I hard-code the public key in my verification code, I 
 will need to update it when I switch to a newer public key?
 Yep, that is why careful matching against various Distinguished Name
 fields is needed.
 
 
 On Sep 06, 2014, at 09:44 PM, Prasad Dabak pda...@icloud.com wrote:
 
 Hello,
 
 Given a signed Windows portable executable, I want to programmatically 
 verify two things using openssl APIs
 
 1. Verify the digital signature.
 2. Confirm that the executable is signed by a specific company using that 
 company's public key.
 
 It seems that part (1) can be done by parsing the signedData attribute in 
 the portable executable, extracting the hashing algorithm and digest stored 
 there, 

Re: Verifying authenticode signature using openssl API

2014-09-09 Thread Kyle Hamilton
http://msdn.microsoft.com/en-us/windows/hardware/gg463180.aspx is the spec for 
the Authenticode PE signature format.

http://msdn.microsoft.com/en-us/gg463119 is the Microsoft PE and COFF 
Specification.

Better download them now before they disappear, they appear to be deprecated in 
favor of Windows 8 format packages (of which I have no information).

On September 9, 2014 10:18:18 AM PST, Prasad Dabak pda...@icloud.com wrote:
Thanks Jacob for your response. Very informative indeed!

Thanks
-Prasad

Sent from my iPhone

 On 09-Sep-2014, at 10:05 pm, Jakob Bohm jb-open...@wisemo.com
wrote:
 
 On 09/09/2014 09:01, Prasad Dabak wrote:
 Thanks Jacob for an elaborate answer. Somehow I never received your
response to my registered email address, hence delay in responding.
 This time I have CC-ed you in addition to the mail list.
 I have a few follow-up questions on your response.
 
 1. So, encryptedDigest  has no relation to the stored
messageDigest? I thought it's a encrypted version of the
messageDigest?
 As far as I recall, there is a chain of 4 digests.  The first digest
 is calculated over the file and is stored in the spcIndirectData. The
 second digest is calculated over the spcIndirectData (the contentInfo
 of the the PKCS#7 structure) and is stored as messageDigest in the
 AuthenticatedAttributes of each PKCS#7 signerInfo.  The third hash
 is calculated over the AuthenticatedAttributes and is signed to
 produce the encryptedDigest in that same signerInfo.  All 3 need to
 be checked to confirm that the file hash is actually (indirectly)
 signed by the encryptedDigest using the public key in the certificate
 whose name is listed in the signerInfo.
 2. I agree that it's better to do cheaper checks first e.g. I am
also matching PE checksum stored in the optional header.
 Indeed, though that is a very weak checksum (file size plus 16 bit
TCP/IP
 checksum of file).  Also it is allowed to be 0 to indicate no
checksum
 (even if you set the checksum, it might be cleared if an
Administrator
 adds his own countersignature to all authorized programs on his
 computers, aka AppLocker).
 3. spcPEImageData is probably relevant only for signing that uses
page hashes?
 I never quite figured out where they store the page hashes. However I
 believe the constant semi-empty spcPEImageData with the
obsolete
 string is the traditional marker to indicate that the signature is
for
 a PE file, and not e.g. a document file with the same hashed
bytestream.
 
 4. PKCS7_verify is already matching the encryptedDigest, do we still
need to validate it ourselves?
 If it is, I am myself guessing a bit as to what that function does
and
 does not check.  But note that it probably doesn't check the full
chain
 of 3 message digests, since at least the digest over the file itself
is
 inside a blob that the PKCS#7 standard has no opinion about.
 5. So, basically are are suggesting to look into the subject string
and see if we can find patterns like /CN=COMPANY-NAME... issuer:
/C=US/O=SIGNER_NAME? How authoritative it is? I mean can someone
else have same COMPANY-NAME and PATTERN-NAME in their certificate?
 Actually, the subject is a data structure (a hierarchical list of
sets
 of tagged strings) and the relevant comparison would be to compare
those
 elements that don't change when getting a new certificate from the
CA.
 It is the CAs responsibility to make sure the don't issue
certificates
 to the wrong people, and if they make a mistake they are expected to
 quickly add the bad certificate to their published CRL, which is why
 you need to check the CRL before trusting the certificate.  An
 additional check is to make sure the CA that issued the intermediary
 certificate that issued the COMAPNY-NAME certificate is actually
one
 of the (few) CAs that COMPANY-NAME is going to buy certificates
from.
  This protects against fake certificates issued by smaller CAs that
 you aren't going to use anyway.
 
 In my case, I am the one who is signing the executable using my
certificate and a cross certificate issued by Microsoft and I want to
programmatically ensure following things.
 
 1. Code is not tampered since it was signed (matching messageDigest
with computed hash)
 Actually matching digest in spcIndirectData with computed hash. Plus
 consistency checks to make sure the signature is actually for a PE
file
 and was not otherwise doctored.  For instance there should be no
bytes
 in the file after the end of the signature blob.
 2. Verifying the digital signature (PKCS7_Verify)
 3. Confirming that the executable is signed by my company
certificate.
 
 I am stuck on part (3) and don't see a clean way apart from matching
strings in subject field?  If I hard-code the public key in my
verification code, I will need to update it when I switch to a newer
public key?
 Yep, that is why careful matching against various Distinguished Name
 fields is needed.
 
 
 On Sep 06, 2014, at 09:44 PM, Prasad Dabak pda...@icloud.com
wrote:
 
 Hello,
 
 Given a 

Re: Verifying authenticode signature using openssl API

2014-09-07 Thread Jakob Bohm

On 07/09/2014 05:43, Prasad Dabak wrote:

Hello,

Given a signed Windows portable executable, I want to programmatically 
verify two things using openssl APIs


1. Verify the digital signature.
2. Confirm that the executable is signed by a specific company using 
that company's public key.


It seems that part (1) can be done by parsing the signedData attribute 
in the portable executable, extracting the hashing algorithm and 
digest stored there, re-computing the digest of the executable using 
the same hashing algorithm and match them.


I have following questions.

1. The signData contains messageDigest (unencrypted) and 
encryptedDigest (encrypted). Is it enough to match messgaeDigest with 
the computed digest? OR we also need to decrypt the encryptedDigest 
using the company public key and match that as well?

Both.

Comparing the stored messageDigest to the actual digest in the
spcIndirectDataContext structure checks that the signature
actually is for this file.  Note that Authenticode defines a
specific file format specific formula for omitting the
signature itself from the input to the message digest.

Decrypting the encryptedDigest (really validating the
signedDigest against a digest of the relevant part of the PKCS#7
structure, the field name is historic) is necessary to check if
the signature is a valid signature made with the expected public
key.  This step is, technically, the actual signature
verififcation, but it is meaningless without all the other checks.

Additionally, for Authenticode, you need to do a few extra things
(that should be done *first*, since they are cheaper than the
actual signature check, and one of them affects the signature
check):

- Verify that the PKCS#7 structure field contentInfo is a
 spcIndirectDataContext structure containing a list of attributes.
 This is consistent with the original PKCS#7 standard/RFC, but
 not entirely with the later e-mail focused CMS standard/RFC.
- Verify that the spcIndirectDataContext structure includes the
 correct set of magic attributes for the file type, as otherwise,
 the signature is not for this file even if the digest value
 matches.  These fields indicate the choice of formula (Subject
 Identification Package) for determining the subset of file bytes
 to pass the the message digest.In particalar, if the spcSipInfo
 field is present it must have the correct value, and check the
 presence of any other file format specific attributes (for PE
 EXE/DLL/OCX/SYS files, this means an spcPEImageData attribute
 of a very specific form that includes the BMPString
 Obsolete to distinguish it from the historic Authenticode1
 signatures).
- Verify that the spcIndirectDataContext structure includes an
 attribute whose OID is the OID of a hash algorithm and contains
 the number of bytes for that type of message digest, and matches
 your own calculation of that message digest of the file type
 specific subset of bytes of the file itself.
- Verify that each signerInfo in signerInfos has at least the
 following authenticated attributes: contentType ==
 spcIndirectDataContext and a messageDigest (see also answer 2) .
 Other authenticated attributes are usually present, but not
 mandatory.
- If there is an authenticated attribute of type spcSpOpusInfo, you
 may want to consider this the file description and information URL
 from the manufacturer who signed this signerInfo, but only after
 all the checks pass.
- If a signerInfo contains one or more unauthenticatedAttributes
 of type counterSignature, those should be validated first as being
 valid signerinfos for signatures of the encryptedDigest of the outer
 signerinfo.  If one of them is, and contains an (inner)
 authenticatedAttribute of type signingTime that countersignature is
 for an entity whose certificate in the certificates collection is
 valid for extended usage purpose timeStamping (including a
 recursive requirement that this purpose is also present for its
 issuer), then the time indicated by that signingTime field overrides
 the value of the local clock when determining the validity of the
 certificates for the signature on that particular outer signerinfo.
- Other spcIndirectDataContext attributes,
 unauthenticatedAttributes and/or authenticatedAttributes are
 usually present, but are not mandatory.  An attribute present
 in the wrong of the attribute lists should also be ignored.
 For example a signingTime in the outer signerinfo cannot be used
 to set the time used for the validity checks of that outer
 signerinfo.
- Verify that each of the outer signerinfos refers to a signature
 in the certificates collection which is valid for the extended
 usage purpose of Code Signing and a basic constraint of CA:FALSE.
 This check may fail for some test signatures, but should not fail
 for real signatures made with officially issued certificates.
 This check can be done during the PKCS7_verify call via callbacks
 etc.

2. What does PKCS7_Verify exactly do? I looked at 

Re: Verifying a signature

2005-05-11 Thread Nils Larsch
Andreas Hoffmann wrote:
...
md_ctx = EVP_MD_CTX_create();
EVP_VerifyInit_ex(md_ctx, EVP_sha1(), NULL );
EVP_VerifyUpdate(md_ctx, data, data_length);
sig_err = EVP_VerifyFinal(md_ctx, signature, signature_length, pkey);
if (sig_err == -1) {
   printf(An error occured while verifying the signature!\n);
   ERR_print_errors_fp (stderr);
   exit(1);
}
else if (sig_err == 0) {
   printf(The signature does not match the data\n);
   ERR_print_errors_fp (stderr);
   exit(1);
}
else {
   printf(OK - The signature does match the data\n);
}
But the result is always signature does not match - although it should.
The errors are:
9876:error:0D07209B:asn1 encoding routines:ASN1_get_object:too 
long:asn1_lib.c:132:
9876:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object 
header:tasn_dec.c:935:
9876:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 
error:tasn_dec.c:304:Type=X509_SIG
what's in signature ?
Nils
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread Andreas Hoffmann
Nils Larsch wrote:
Andreas Hoffmann wrote:
...
md_ctx = EVP_MD_CTX_create();
EVP_VerifyInit_ex(md_ctx, EVP_sha1(), NULL );
EVP_VerifyUpdate(md_ctx, data, data_length);
sig_err = EVP_VerifyFinal(md_ctx, signature, signature_length, pkey);
if (sig_err == -1) {
   printf(An error occured while verifying the signature!\n);
   ERR_print_errors_fp (stderr);
   exit(1);
}
else if (sig_err == 0) {
   printf(The signature does not match the data\n);
   ERR_print_errors_fp (stderr);
   exit(1);
}
else {
   printf(OK - The signature does match the data\n);
}
But the result is always signature does not match - although it 
should.
The errors are:
9876:error:0D07209B:asn1 encoding routines:ASN1_get_object:too 
long:asn1_lib.c:132:
9876:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object 
header:tasn_dec.c:935:
9876:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested 
asn1 error:tasn_dec.c:304:Type=X509_SIG

what's in signature ?
signature is a uint8_t *signature; - it is a signed value, which is 
received within an IKE-exchange and has to be verified.

BTW: EVP_VerifyFinal returns 0 not -1
Thanks
Andreas
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread El hallabi-Kettani Abderrahmane
I think that the format of the signature make problem,
normally the standard format of signature is a DER
format.

Abdou,

 






__ 
Découvrez le nouveau Yahoo! Mail : 250 Mo d'espace de stockage pour vos mails ! 
Créez votre Yahoo! Mail sur http://fr.mail.yahoo.com/
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread Andreas Hoffmann
The signature contains the value which is extracted from the 
socket-datastream and is 128Bytes (1024bit) long.
What is in a signature in DER format? - Is it just the signature itself 
or is there additional information?

What do the error-messages mean -
- Is there some problem while verifying (wrong input-values,...) OR
- Is the verification completed successfully but the signature simply 
does not match the data?

Andreas
the errors again:
9876:error:0D07209B:asn1 encoding routines:ASN1_get_object:too 
long:asn1_lib.c:132:
9876:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object 
header:tasn_dec.c:935:
9876:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 
error:tasn_dec.c:304:Type=X509_SIG

El hallabi-Kettani Abderrahmane schrieb:
I think that the format of the signature make problem,
normally the standard format of signature is a DER
format.
Abdou,
 

__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread El hallabi-Kettani Abderrahmane
make this test to see exactly what you have as 
errors.

 if (err != 1) {
ERR_print_errors_fp (stderr);
exit (1);
  }

Abdou,








__ 
Découvrez le nouveau Yahoo! Mail : 250 Mo d'espace de stockage pour vos mails ! 
Créez votre Yahoo! Mail sur http://fr.mail.yahoo.com/
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread Andreas Hoffmann

make this test to see exactly what you have as 
errors.

if (err != 1) {
   ERR_print_errors_fp (stderr);
   exit (1);
 }
Abdou,
 

That's almost exactly how I got the errors
I did:
sig_err = EVP_VerifyFinal(md_ctx, signature, signature_length, pkey);
printf(Signature-Verification: %d\n,sig_err);
if (sig_err == -1) {
   printf(An error occured while verifying the signature!\n);
   ERR_print_errors_fp (stderr);
   exit(1);
}
else if (sig_err == 0) {
   printf(The signature does not match the data\n);
   ERR_print_errors_fp (stderr);
   exit(1);
}
else {
   printf(OK - The signature does match the data\n);
}
And got:
Signature-Verification: 0
The signature does not match the data
9876:error:0D07209B:asn1 encoding routines:ASN1_get_object:too 
long:asn1_lib.c:132:
9876:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object 
header:tasn_dec.c:935:
9876:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 
error:tasn_dec.c:304:Type=X509_SIG

Any ideas?
Andreas
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread Dr. Stephen Henson
On Wed, May 11, 2005, Andreas Hoffmann wrote:

 The signature contains the value which is extracted from the 
 socket-datastream and is 128Bytes (1024bit) long.
 What is in a signature in DER format? - Is it just the signature itself 
 or is there additional information?
 
 What do the error-messages mean -
 - Is there some problem while verifying (wrong input-values,...) OR
 - Is the verification completed successfully but the signature simply 
 does not match the data?
 
 Andreas
 
 the errors again:
 9876:error:0D07209B:asn1 encoding routines:ASN1_get_object:too 
 long:asn1_lib.c:132:
 9876:error:0D068066:asn1 encoding routines:ASN1_CHECK_TLEN:bad object 
 header:tasn_dec.c:935:
 9876:error:0D07803A:asn1 encoding routines:ASN1_ITEM_EX_D2I:nested asn1 
 error:tasn_dec.c:304:Type=X509_SIG
 
 

This needs a bit of background first.

EVP_{Sign,Verify}*() with an RSA key use PKCS#1 for signatures. This consists
of DER DigestInfo structure (X509_SIG in OpenSSL) encrypted using the
appropriate RSA key. This structure is simply the digest value and the digest
algorithm in use.

When the signature is verified OpenSSL decrypts and attempts to ASN1 parse the
result.

If the ASN1 parsing fails you get that error. It is unlikely that that error
could be produce by an accident: it may well be in a different format.

To see the format used you can do:

openssl rsautl -verify -certin -in signature -inkey cert.pem -hexdump

and post the result. Also try it with the -asn1parse option instead of
-hexdump.

Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread Andreas Hoffmann

To see the format used you can do:
openssl rsautl -verify -certin -in signature -inkey cert.pem -hexdump
and post the result. Also try it with the -asn1parse option instead of
-hexdump.
 

# openssl rsautl -verify -certin -in signature -inkey vpn_test_konz.pem 
-asn1parse
Error in encoding
15952:error:0D07209B:asn1 encoding routines:ASN1_get_object:too 
long:asn1_lib.c:132:

# openssl rsautl -verify -certin -in signature -inkey vpn_test_konz.pem 
-hexdump
 - 4f 23 50 15 e1 24 51 a2-4d 86 28 4c 4a 3b 50 29   O#P..$Q.M.(LJ;P)
0010 - f0 13 ad 14   

this is exactly the expected data:
4f235015 e12451a2 4d86284c 4a3b5029 f013ad14
So is there a way to verify the hex-data?
Andreas
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Verifying a signature

2005-05-11 Thread Dr. Stephen Henson
On Wed, May 11, 2005, Andreas Hoffmann wrote:

 
 To see the format used you can do:
 
 openssl rsautl -verify -certin -in signature -inkey cert.pem -hexdump
 
 and post the result. Also try it with the -asn1parse option instead of
 -hexdump.
 
 
  
 
 # openssl rsautl -verify -certin -in signature -inkey vpn_test_konz.pem 
 -asn1parse
 Error in encoding
 15952:error:0D07209B:asn1 encoding routines:ASN1_get_object:too 
 long:asn1_lib.c:132:
 
 # openssl rsautl -verify -certin -in signature -inkey vpn_test_konz.pem 
 -hexdump
  - 4f 23 50 15 e1 24 51 a2-4d 86 28 4c 4a 3b 50 29   O#P..$Q.M.(LJ;P)
 0010 - f0 13 ad 14   
 
 this is exactly the expected data:
 4f235015 e12451a2 4d86284c 4a3b5029 f013ad14
 
 So is there a way to verify the hex-data?
 

Well that means whatever generated that signature is using a non-standard
technique, if it can be made to use PKCS#1 then that would be best. That isn't
hard to do if you've any control over the format.

Alternatively you can manually do the compare. In outline you'd call
RSA_public_decrypt() to obtain the signed digest, check its length is correct,
call EVP_Digest{Init,Update,Final) to calculate the expected digest and
finally compare the two.

Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]