UsingTasks are not collected expectedly when imports are involved.
[mono.git] / mcs / class / Mono.Security / Mono.Security.X509 / X509CRL.cs
index d3a86fc9e2882fed51caf60aaa02f1ac8c7bd4b9..daa5a5841ff8f37190ef584e49543e7c648768af 100644 (file)
@@ -2,11 +2,10 @@
 // X509CRL.cs: Handles X.509 certificates revocation lists.
 //
 // Author:
-//     Sebastien Pouliot  <sebastien@ximian.com>
+//     Sebastien Pouliot  <sebastien@xamarin.com>
 //
-// (C) 2004 Novell (http://www.novell.com)
-//
-
+// Copyright (C) 2004,2006 Novell Inc. (http://www.novell.com)
+// Copyright 2013 Xamarin Inc. (http://www.xamarin.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
@@ -34,6 +33,7 @@ using System.Globalization;
 using System.IO;
 using System.Security.Cryptography;
 
+using Mono.Security.Cryptography;
 using Mono.Security.X509.Extensions;
 
 namespace Mono.Security.X509 {
@@ -60,9 +60,7 @@ namespace Mono.Security.X509 {
         *      crlExtensions           [0] Extensions OPTIONAL }
         *              -- if present, MUST be v2
         */
-#if INSIDE_CORLIB
-       internal
-#else
+#if !INSIDE_CORLIB
        public 
 #endif
        class X509Crl {
@@ -123,6 +121,7 @@ namespace Mono.Security.X509 {
                private byte[] signature;
                private X509ExtensionCollection extensions;
                private byte[] encoded;
+               private byte[] hash_value;
 
                public X509Crl (byte[] crl) 
                {
@@ -167,9 +166,14 @@ namespace Mono.Security.X509 {
                                }
                                // CertificateList / TBSCertList / revokedCertificates  SEQUENCE OF SEQUENCE  {
                                entries = new ArrayList ();
-                               ASN1 revokedCertificates = next;
-                               for (int i=0; i < revokedCertificates.Count; i++) {
-                                       entries.Add (new X509CrlEntry (revokedCertificates [i]));
+                               // this is OPTIONAL so it may not be present if no entries exists
+                               if ((next != null) && (next.Tag == 0x30)) {
+                                       ASN1 revokedCertificates = next;
+                                       for (int i=0; i < revokedCertificates.Count; i++) {
+                                               entries.Add (new X509CrlEntry (revokedCertificates [i]));
+                                       }
+                               } else {
+                                       n--;
                                }
                                // CertificateList / TBSCertList / crlExtensions [0] Extensions OPTIONAL }
                                ASN1 extns = toBeSigned [n];
@@ -209,6 +213,18 @@ namespace Mono.Security.X509 {
                        get { return extensions; }
                }
 
+               public byte[] Hash {
+                       get {
+                               if (hash_value == null) {
+                                       ASN1 encodedCRL = new ASN1 (encoded);
+                                       byte[] toBeSigned = encodedCRL [0].GetBytes ();
+                                       using (var ha = PKCS1.CreateFromOid (signatureOID))
+                                               hash_value = ha.ComputeHash (toBeSigned);
+                               }
+                               return hash_value;
+                       }
+               }
+
                public string IssuerName {
                        get { return issuer; }
                }
@@ -233,12 +249,16 @@ namespace Mono.Security.X509 {
                        }
                }
 
+               public byte[] RawData {
+                       get { return (byte[]) encoded.Clone (); }
+               }
+
                public byte Version {
                        get { return version; }
                }
 
                public bool IsCurrent {
-                       get { return WasCurrent (DateTime.UtcNow); }
+                       get { return WasCurrent (DateTime.Now); }
                }
 
                public bool WasCurrent (DateTime instant) 
@@ -297,20 +317,25 @@ namespace Mono.Security.X509 {
 
                        // 1. x509 certificate must be a CA certificate (unknown for v1 or v2 certs)
                        if (x509.Version >= 3) {
-                               // 1.1. Check for "cRLSign" bit in KeyUsage extension
-                               X509Extension ext = x509.Extensions ["2.5.29.15"];
-                               if (ext != null) {
-                                       KeyUsageExtension keyUsage = new KeyUsageExtension (ext);
-                                       if (!keyUsage.Support (KeyUsages.cRLSign))
-                                               return false;
-                               }
+                               BasicConstraintsExtension basicConstraints = null;
                                // 1.2. Check for ca = true in BasicConstraint
-                               ext = x509.Extensions ["2.5.29.19"];
+                               X509Extension ext = x509.Extensions ["2.5.29.19"];
                                if (ext != null) {
-                                       BasicConstraintsExtension basicConstraints = new BasicConstraintsExtension (ext);
+                                       basicConstraints = new BasicConstraintsExtension (ext);
                                        if (!basicConstraints.CertificateAuthority)
                                                return false;
                                }
+                               // 1.1. Check for "cRLSign" bit in KeyUsage extension
+                               ext = x509.Extensions ["2.5.29.15"];
+                               if (ext != null) {
+                                       KeyUsageExtension keyUsage = new KeyUsageExtension (ext);
+                                       if (!keyUsage.Support (KeyUsages.cRLSign)) {
+                                               // 2nd chance if basicConstraints is CertificateAuthority
+                                               // and KeyUsage support digitalSignature
+                                               if ((basicConstraints == null) || !keyUsage.Support (KeyUsages.digitalSignature))
+                                                       return false;
+                                       }
+                               }
                        }
                        // 2. CRL issuer must match CA subject name
                        if (issuer != x509.SubjectName)
@@ -324,22 +349,13 @@ namespace Mono.Security.X509 {
                        }
                }
 
-               private byte[] GetHash (string hashName) 
-               {
-                       ASN1 encodedCRL = new ASN1 (encoded);
-                       byte[] toBeSigned = encodedCRL [0].GetBytes ();
-                       HashAlgorithm ha = HashAlgorithm.Create (hashName);
-                       return ha.ComputeHash (toBeSigned);
-               }
-
                internal bool VerifySignature (DSA dsa) 
                {
                        if (signatureOID != "1.2.840.10040.4.3")
                                throw new CryptographicException ("Unsupported hash algorithm: " + signatureOID);
                        DSASignatureDeformatter v = new DSASignatureDeformatter (dsa);
                        // only SHA-1 is supported
-                       string hashName = "SHA1";
-                       v.SetHashAlgorithm (hashName);
+                       v.SetHashAlgorithm ("SHA1");
                        ASN1 sign = new ASN1 (signature);
                        if ((sign == null) || (sign.Count != 2))
                                return false;
@@ -347,34 +363,22 @@ namespace Mono.Security.X509 {
                        byte[] part1 = sign [0].Value;
                        byte[] part2 = sign [1].Value;
                        byte[] sig = new byte [40];
-                       Buffer.BlockCopy (part1, 0, sig, (20 - part1.Length), part1.Length);
-                       Buffer.BlockCopy (part2, 0, sig, (40 - part2.Length), part2.Length);
-                       return v.VerifySignature (GetHash (hashName), sig);
+                       // parts may be less than 20 bytes (i.e. first bytes were 0x00)
+                       // parts may be more than 20 bytes (i.e. first byte > 0x80, negative)
+                       int s1 = System.Math.Max (0, part1.Length - 20);
+                       int e1 = System.Math.Max (0, 20 - part1.Length);
+                       Buffer.BlockCopy (part1, s1, sig, e1, part1.Length - s1);
+                       int s2 = System.Math.Max (0, part2.Length - 20);
+                       int e2 = System.Math.Max (20, 40 - part2.Length);
+                       Buffer.BlockCopy (part2, s2, sig, e2, part2.Length - s2);
+                       return v.VerifySignature (Hash, sig);
                }
 
                internal bool VerifySignature (RSA rsa) 
                {
                        RSAPKCS1SignatureDeformatter v = new RSAPKCS1SignatureDeformatter (rsa);
-                       string hashName = null;
-                       switch (signatureOID) {
-                               // MD2 with RSA encryption 
-                               case "1.2.840.113549.1.1.2":
-                                       // maybe someone installed MD2 ?
-                                       hashName = "MD2";
-                                       break;
-                               // MD5 with RSA encryption 
-                               case "1.2.840.113549.1.1.4":
-                                       hashName = "MD5";
-                                       break;
-                               // SHA-1 with RSA Encryption 
-                               case "1.2.840.113549.1.1.5":
-                                       hashName = "SHA1";
-                                       break;
-                               default:
-                                       throw new CryptographicException ("Unsupported hash algorithm: " + signatureOID);
-                       }
-                       v.SetHashAlgorithm (hashName);
-                       return v.VerifySignature (GetHash (hashName), signature);
+                       v.SetHashAlgorithm (PKCS1.HashNameFromOid (signatureOID));
+                       return v.VerifySignature (Hash, signature);
                }
 
                public bool VerifySignature (AsymmetricAlgorithm aa)