diff options
Diffstat (limited to 'mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs')
-rwxr-xr-x | mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs | 123 |
1 files changed, 42 insertions, 81 deletions
diff --git a/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs index ea0bd30e242..4d30ea38aab 100755 --- a/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs +++ b/mcs/class/Mono.Security/Mono.Security.Authenticode/AuthenticodeDeformatter.cs @@ -5,7 +5,9 @@ // Sebastien Pouliot <sebastien@ximian.com> // // (C) 2003 Motus Technologies Inc. (http://www.motus.com) -// Copyright (C) 2004 Novell, Inc (http://www.novell.com) +// (C) 2004 Novell (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 @@ -54,9 +56,6 @@ namespace Mono.Security.Authenticode { private DateTime timestamp; private X509Certificate signingCertificate; private int reason; - private bool trustedRoot; - private bool trustedTimestampRoot; - private byte[] entry; private X509Chain signerChain; private X509Chain timestampChain; @@ -70,20 +69,17 @@ namespace Mono.Security.Authenticode { public AuthenticodeDeformatter (string fileName) : this () { - FileName = fileName; + if (!CheckSignature (fileName)) { + // invalid or no signature + if (signedHash != null) + throw new COMException ("Invalid signature"); + // no exception is thrown when there's no signature in the PE file + } } public string FileName { get { return filename; } - set { - Reset (); - try { - CheckSignature (value); - } - catch { - reason = 1; - } - } + set { CheckSignature (value); } } public byte[] Hash { @@ -104,7 +100,7 @@ namespace Mono.Security.Authenticode { public bool IsTrusted () { - if (entry == null) { + if (rawData == null) { reason = 1; return false; } @@ -114,13 +110,13 @@ namespace Mono.Security.Authenticode { return false; } - if ((signerChain.Root == null) || !trustedRoot) { + if (signerChain.Root == null) { reason = 6; return false; } if (timestamp != DateTime.MinValue) { - if ((timestampChain.Root == null) || !trustedTimestampRoot) { + if (timestampChain.Root == null) { reason = 6; return false; } @@ -142,11 +138,7 @@ namespace Mono.Security.Authenticode { } public byte[] Signature { - get { - if (entry == null) - return null; - return (byte[]) entry.Clone (); - } + get { return (byte[]) rawData.Clone (); } } public DateTime Timestamp { @@ -164,58 +156,43 @@ namespace Mono.Security.Authenticode { private bool CheckSignature (string fileName) { filename = fileName; - base.Open (filename); - entry = base.GetSecurityEntry (); - if (entry == null) { - // no signature is present - reason = 1; - base.Close (); + + // by default we try with MD5 + string hashName = "MD5"; + // compare the signature's hash with the hash of the file + hash = HashFile (filename, hashName); + + // is a signature present ? + if (rawData == null) return false; - } - PKCS7.ContentInfo ci = new PKCS7.ContentInfo (entry); - if (ci.ContentType != PKCS7.Oid.signedData) { - base.Close (); + PKCS7.ContentInfo ci = new PKCS7.ContentInfo (rawData); + if (ci.ContentType != PKCS7.Oid.signedData) return false; - } PKCS7.SignedData sd = new PKCS7.SignedData (ci.Content); - if (sd.ContentInfo.ContentType != spcIndirectDataContext) { - base.Close (); + if (sd.ContentInfo.ContentType != spcIndirectDataContext) return false; - } coll = sd.Certificates; ASN1 spc = sd.ContentInfo.Content; signedHash = spc [0][1][1]; - - HashAlgorithm ha = null; - switch (signedHash.Length) { - case 16: - ha = HashAlgorithm.Create ("MD5"); - hash = GetHash (ha); - break; - case 20: - ha = HashAlgorithm.Create ("SHA1"); - hash = GetHash (ha); - break; - default: - reason = 5; - base.Close (); - return false; + if (signedHash.Length == 20) { + // seems to be SHA-1, restart hashing + hashName = "SHA1"; + hash = HashFile (filename, hashName); } - base.Close (); if (!signedHash.CompareValue (hash)) return false; // messageDigest is a hash of spcIndirectDataContext (which includes the file hash) byte[] spcIDC = spc [0].Value; - ha.Initialize (); // re-using hash instance + HashAlgorithm ha = HashAlgorithm.Create (hashName); byte[] messageDigest = ha.ComputeHash (spcIDC); - return VerifySignature (sd, messageDigest, ha); + return VerifySignature (sd, messageDigest, hashName); } private bool CompareIssuerSerial (string issuer, byte[] serial, X509Certificate x509) @@ -235,7 +212,7 @@ namespace Mono.Security.Authenticode { } //private bool VerifySignature (ASN1 cs, byte[] calculatedMessageDigest, string hashName) - private bool VerifySignature (PKCS7.SignedData sd, byte[] calculatedMessageDigest, HashAlgorithm ha) + private bool VerifySignature (PKCS7.SignedData sd, byte[] calculatedMessageDigest, string hashName) { string contentType = null; ASN1 messageDigest = null; @@ -264,7 +241,7 @@ namespace Mono.Security.Authenticode { case "1.3.6.1.4.1.311.2.1.12": // spcSpOpusInfo (Microsoft code signing) try { - spcSpOpusInfo = System.Text.Encoding.UTF8.GetString (attr[1][0][0][0].Value); + spcSpOpusInfo = System.Text.Encoding.UTF8.GetString (attr[1][0][1][0].Value); } catch (NullReferenceException) { spcSpOpusInfo = null; @@ -284,13 +261,13 @@ namespace Mono.Security.Authenticode { return false; // verify signature - string hashOID = CryptoConfig.MapNameToOID (ha.ToString ()); + string hashOID = CryptoConfig.MapNameToOID (hashName); // change to SET OF (not [0]) as per PKCS #7 1.5 ASN1 aa = new ASN1 (0x31); foreach (ASN1 a in sd.SignerInfo.AuthenticatedAttributes) aa.Add (a); - ha.Initialize (); + HashAlgorithm ha = HashAlgorithm.Create (hashName); byte[] p7hash = ha.ComputeHash (aa.GetBytes ()); byte[] signature = sd.SignerInfo.Signature; @@ -304,9 +281,10 @@ namespace Mono.Security.Authenticode { RSACryptoServiceProvider rsa = (RSACryptoServiceProvider) x509.RSA; if (rsa.VerifyHash (p7hash, hashOID, signature)) { signerChain.LoadCertificates (coll); - trustedRoot = signerChain.Build (x509); - signingCertificate = x509; - break; + if (signerChain.Build (x509)) + signingCertificate = x509; + else + return false; } } } @@ -322,18 +300,17 @@ namespace Mono.Security.Authenticode { // countersignature (1 2 840 113549 1 9 6) // SET { PKCS7.SignerInfo cs = new PKCS7.SignerInfo (attr [1]); - trustedTimestampRoot = VerifyCounterSignature (cs, signature); - break; + return VerifyCounterSignature (cs, signature, hashName); default: // we don't support other unauthenticated attributes break; } } - return (trustedRoot && trustedTimestampRoot); + return true; } - private bool VerifyCounterSignature (PKCS7.SignerInfo cs, byte[] signature) + private bool VerifyCounterSignature (PKCS7.SignerInfo cs, byte[] signature, string hashName) { // SEQUENCE { // INTEGER 1 @@ -380,7 +357,6 @@ namespace Mono.Security.Authenticode { if (messageDigest == null) return false; // TODO: must be read from the ASN.1 structure - string hashName = null; switch (messageDigest.Length) { case 16: hashName = "MD5"; @@ -421,20 +397,5 @@ namespace Mono.Security.Authenticode { // no certificate can verify this signature! return false; } - - private void Reset () - { - filename = null; - entry = null; - hash = null; - signedHash = null; - signingCertificate = null; - reason = -1; - trustedRoot = false; - trustedTimestampRoot = false; - signerChain.Reset (); - timestampChain.Reset (); - timestamp = DateTime.MinValue; - } } } |