// 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 {
return false;
}
- reason = 0;
+ if (reason == -1)
+ reason = 0;
return true;
}
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;
}
break;
default:
reason = 5;
- base.Close ();
+ Close ();
return false;
}
- base.Close ();
+ Close ();
if (!signedHash.CompareValue (hash)) {
reason = 2;
- return false;
}
// messageDigest is a hash of spcIndirectDataContext (which includes the file hash)
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)
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;
+ }
}
}
// 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);
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));
}
}
}
}
+
+#endif
+