New test.
[mono.git] / mcs / class / corlib / Mono.Security.Authenticode / AuthenticodeDeformatter.cs
old mode 100755 (executable)
new mode 100644 (file)
index a9296af..647fd41
@@ -5,7 +5,7 @@
 //     Sebastien Pouliot <sebastien@ximian.com>
 //
 // (C) 2003 Motus Technologies Inc. (http://www.motus.com)
-// Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004-2006 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
+#if !MOONLIGHT
+
 using System;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Security;
 using System.Security.Cryptography;
 
+using Mono.Security.Cryptography;
 using Mono.Security.X509;
 
 namespace Mono.Security.Authenticode {
@@ -140,7 +143,8 @@ namespace Mono.Security.Authenticode {
                                return false;
                        }
 
-                       reason = 0;
+                       if (reason == -1)
+                               reason = 0;
                        return true;
                }
 
@@ -167,24 +171,24 @@ namespace Mono.Security.Authenticode {
                private bool CheckSignature (string fileName) 
                {
                        filename = fileName;
-                       base.Open (filename);
-                       entry = base.GetSecurityEntry ();
+                       Open (filename);
+                       entry = GetSecurityEntry ();
                        if (entry == null) {
                                // no signature is present
                                reason = 1;
-                               base.Close ();
+                               Close ();
                                return false;
                        }
 
                        PKCS7.ContentInfo ci = new PKCS7.ContentInfo (entry);
                        if (ci.ContentType != PKCS7.Oid.signedData) {
-                               base.Close ();
+                               Close ();
                                return false;
                        }
 
                        PKCS7.SignedData sd = new PKCS7.SignedData (ci.Content);
                        if (sd.ContentInfo.ContentType != spcIndirectDataContext) {
-                               base.Close ();
+                               Close ();
                                return false;
                        }
 
@@ -205,20 +209,22 @@ namespace Mono.Security.Authenticode {
                                        break;
                                default:
                                        reason = 5;
-                                       base.Close ();
+                                       Close ();
                                        return false;
                        }
-                       base.Close ();
+                       Close ();
 
-                       if (!signedHash.CompareValue (hash))
-                               return false;
+                       if (!signedHash.CompareValue (hash)) {
+                               reason = 2;
+                       }
 
                        // messageDigest is a hash of spcIndirectDataContext (which includes the file hash)
                        byte[] spcIDC = spc [0].Value;
                        ha.Initialize (); // re-using hash instance
                        byte[] messageDigest = ha.ComputeHash (spcIDC);
 
-                       return VerifySignature (sd, messageDigest, ha);
+                       bool sign = VerifySignature (sd, messageDigest, ha);
+                       return (sign && (reason == 0));
                }
 
                private bool CompareIssuerSerial (string issuer, byte[] serial, X509Certificate x509) 
@@ -304,32 +310,39 @@ namespace Mono.Security.Authenticode {
                                if (CompareIssuerSerial (issuer, serial, x509)) {
                                        // don't verify is key size don't match
                                        if (x509.PublicKey.Length > (signature.Length >> 3)) {
+                                               // return the signing certificate even if the signature isn't correct
+                                               // (required behaviour for 2.0 support)
+                                               signingCertificate = x509;
                                                RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA;
                                                if (rsa.VerifyHash (p7hash, hashOID, signature)) {
                                                        signerChain.LoadCertificates (coll);
                                                        trustedRoot = signerChain.Build (x509);
-                                                       signingCertificate = x509;
                                                        break; 
                                                }
                                        }
                                }
                        }
 
-                       for (int i=0; i < sd.SignerInfo.UnauthenticatedAttributes.Count; i++) {
-                               ASN1 attr = (ASN1) sd.SignerInfo.UnauthenticatedAttributes [i];
-                               string oid = ASN1Convert.ToOid (attr [0]);
-                               switch (oid) {
+                       // timestamp signature is optional
+                       if (sd.SignerInfo.UnauthenticatedAttributes.Count == 0) {
+                               trustedTimestampRoot = true;
+                       }  else {
+                               for (int i = 0; i < sd.SignerInfo.UnauthenticatedAttributes.Count; i++) {
+                                       ASN1 attr = (ASN1) sd.SignerInfo.UnauthenticatedAttributes[i];
+                                       string oid = ASN1Convert.ToOid (attr[0]);
+                                       switch (oid) {
                                        case PKCS7.Oid.countersignature:
                                                // SEQUENCE {
                                                //   OBJECT IDENTIFIER
                                                //     countersignature (1 2 840 113549 1 9 6)
                                                //   SET {
-                                               PKCS7.SignerInfo cs = new PKCS7.SignerInfo (attr [1]);
+                                               PKCS7.SignerInfo cs = new PKCS7.SignerInfo (attr[1]);
                                                trustedTimestampRoot = VerifyCounterSignature (cs, signature);
                                                break;
                                        default:
                                                // we don't support other unauthenticated attributes
                                                break;
+                                       }
                                }
                        }
 
@@ -398,7 +411,6 @@ namespace Mono.Security.Authenticode {
 
                        // verify signature
                        byte[] counterSignature = cs.Signature;
-                       string hashOID = CryptoConfig.MapNameToOID (hashName);
 
                        // change to SET OF (not [0]) as per PKCS #7 1.5
                        ASN1 aa = new ASN1 (0x31);
@@ -411,10 +423,13 @@ namespace Mono.Security.Authenticode {
                        byte[] serial = cs.SerialNumber;
                        foreach (X509Certificate x509 in coll) {
                                if (CompareIssuerSerial (issuer, serial, x509)) {
-                                       // don't verify if key size don't match
-                                       if (x509.PublicKey.Length > (counterSignature.Length >> 3)) {
+                                       if (x509.PublicKey.Length > counterSignature.Length) {
                                                RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA;
-                                               if (rsa.VerifyHash (p7hash, hashOID, counterSignature)) {
+                                               // we need to HACK around bad (PKCS#1 1.5) signatures made by Verisign Timestamp Service
+                                               // and this means copying stuff into our own RSAManaged to get the required flexibility
+                                               RSAManaged rsam = new RSAManaged ();
+                                               rsam.ImportParameters (rsa.ExportParameters (false));
+                                               if (PKCS1.Verify_v15 (rsam, ha, p7hash, counterSignature, true)) {
                                                        timestampChain.LoadCertificates (coll);
                                                        return (timestampChain.Build (x509));
                                                }
@@ -441,3 +456,6 @@ namespace Mono.Security.Authenticode {
                }
        }
 }
+
+#endif
+