2008-01-10 Sebastien Pouliot <sebastien@ximian.com>
authorSebastien Pouliot <sebastien@ximian.com>
Thu, 10 Jan 2008 19:12:50 +0000 (19:12 -0000)
committerSebastien Pouliot <sebastien@ximian.com>
Thu, 10 Jan 2008 19:12:50 +0000 (19:12 -0000)
* PKCS1.cs: Add a new method that optionally checks for badly
padding, technically invalid, PKCS#1 block. This is required to
support timestamping verification for Authenticode (since the
main timestamping service does this). Fix for #350958

svn path=/trunk/mcs/; revision=92615

mcs/class/corlib/Mono.Security.Cryptography/ChangeLog
mcs/class/corlib/Mono.Security.Cryptography/PKCS1.cs

index 2daed353bec1f98bbd91a4cff93461152263cb9f..1538ef9ff603fa056df2fcd81b7345df266a4d6b 100644 (file)
@@ -1,3 +1,10 @@
+2008-01-10  Sebastien Pouliot  <sebastien@ximian.com>
+
+       * PKCS1.cs: Add a new method that optionally checks for badly 
+       padding, technically invalid, PKCS#1 block. This is required to
+       support timestamping verification for Authenticode (since the 
+       main timestamping service does this). Fix for #350958
+
 2007-11-18  Sebastien Pouliot  <sebastien@ximian.com>
 
        * RSAManaged.cs: Fix the rare case where the inverse of q modulo p 
index f168a29c48b41619723efa867f6952174e03a490..2aad2426d971231e8e94322f5d8ef1fa6498ea3c 100644 (file)
@@ -290,13 +290,39 @@ namespace Mono.Security.Cryptography {
                // PKCS #1 v.2.1, Section 8.2.2
                // RSASSA-PKCS1-V1_5-VERIFY ((n, e), M, S)
                public static bool Verify_v15 (RSA rsa, HashAlgorithm hash, byte[] hashValue, byte[] signature) 
+               {
+                       return Verify_v15 (rsa, hash, hashValue, signature, false);
+               }
+
+               // DO NOT USE WITHOUT A VERY GOOD REASON
+               public static bool Verify_v15 (RSA rsa, HashAlgorithm hash, byte [] hashValue, byte [] signature, bool tryNonStandardEncoding)
                {
                        int size = (rsa.KeySize >> 3); // div 8
                        byte[] s = OS2IP (signature);
                        byte[] m = RSAVP1 (rsa, s);
                        byte[] EM2 = I2OSP (m, size);
                        byte[] EM = Encode_v15 (hash, hashValue, size);
-                       return Compare (EM, EM2);
+                       bool result = Compare (EM, EM2);
+                       if (result || !tryNonStandardEncoding)
+                               return result;
+
+                       // NOTE: some signatures don't include the hash OID (pretty lame but real)
+                       // and compatible with MS implementation. E.g. Verisign Authenticode Timestamps
+
+                       // we're making this "as safe as possible"
+                       if ((EM2 [0] != 0x00) || (EM2 [1] != 0x01))
+                               return false;
+                       int i;
+                       for (i = 2; i < EM2.Length - hashValue.Length - 1; i++) {
+                               if (EM2 [i] != 0xFF)
+                                       return false;
+                       }
+                       if (EM2 [i++] != 0x00)
+                               return false;
+
+                       byte [] decryptedHash = new byte [hashValue.Length];
+                       Buffer.BlockCopy (EM2, i, decryptedHash, 0, decryptedHash.Length);
+                       return Compare (decryptedHash, hashValue);
                }
        
                // PKCS #1 v.2.1, Section 9.2