* roottypes.cs: Rename from tree.cs.
[mono.git] / mcs / class / Mono.Security / Mono.Security / PKCS7.cs
index 54e030df7be9b93c945ed638f6a5b964523e07a7..a03b405f1807645c98af0863e350eae5019eba02 100644 (file)
@@ -2,13 +2,12 @@
 // PKCS7.cs: PKCS #7 - Cryptographic Message Syntax Standard 
 //     http://www.rsasecurity.com/rsalabs/pkcs/pkcs-7/index.html
 //
-// Author:
+// Authors:
 //     Sebastien Pouliot <sebastien@ximian.com>
+//     Daniel Granath <dgranath#gmail.com>
 //
 // (C) 2002, 2003 Motus Technologies Inc. (http://www.motus.com)
-// (C) 2004 Novell (http://www.novell.com)
-//
-
+// Copyright (C) 2004-2005 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
@@ -549,6 +548,7 @@ namespace Mono.Security {
                        private ArrayList crls;
                        private SignerInfo signerInfo;
                        private bool mda;
+                       private bool signed;
 
                        public SignedData () 
                        {
@@ -558,6 +558,7 @@ namespace Mono.Security {
                                crls = new ArrayList ();
                                signerInfo = new SignerInfo ();
                                mda = true;
+                               signed = false;
                        }
 
                        public SignedData (byte[] data) 
@@ -712,7 +713,7 @@ namespace Mono.Security {
                                // contentInfo ContentInfo,
                                ASN1 ci = contentInfo.ASN1;
                                signedData.Add (ci);
-                               if (hashAlgorithm != null) {
+                               if (!signed && (hashAlgorithm != null)) {
                                        if (mda) {
                                                // Use authenticated attributes for signature
                                                
@@ -734,6 +735,7 @@ namespace Mono.Security {
                                                byte[] sig = ha.ComputeHash (ci[1][0].Value);
                                                signerInfo.Signature = r.CreateSignature (sig);
                                        }
+                                       signed = true;
                                }
 
                                // certificates [0] IMPLICIT ExtendedCertificatesAndCertificates OPTIONAL,
@@ -832,8 +834,9 @@ namespace Mono.Security {
                                }
 
                                // digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier
-                               ASN1 digestEncryptionAlgorithm = asn1 [0][n++];
-                               string digestEncryptionAlgorithmOid = ASN1Convert.ToOid (digestEncryptionAlgorithm [0]);
+                               n++;
+                               // ASN1 digestEncryptionAlgorithm = asn1 [0][n++];
+                               // string digestEncryptionAlgorithmOid = ASN1Convert.ToOid (digestEncryptionAlgorithm [0]);
 
                                // encryptedDigest EncryptedDigest
                                ASN1 encryptedDigest = asn1 [0][n++];
@@ -931,6 +934,7 @@ namespace Mono.Security {
                                ASN1 aa = null;
                                if (authenticatedAttributes.Count > 0) {
                                        aa = signerInfo.Add (new ASN1 (0xA0));
+                                       authenticatedAttributes.Sort(new SortedSet ());
                                        foreach (ASN1 attr in authenticatedAttributes)
                                                aa.Add (attr);
                                }
@@ -959,6 +963,7 @@ namespace Mono.Security {
                                // unauthenticatedAttributes [1] IMPLICIT Attributes OPTIONAL 
                                if (unauthenticatedAttributes.Count > 0) {
                                        ASN1 ua = signerInfo.Add (new ASN1 (0xA1));
+                                       unauthenticatedAttributes.Sort(new SortedSet ());
                                        foreach (ASN1 attr in unauthenticatedAttributes)
                                                ua.Add (attr);
                                }
@@ -970,5 +975,44 @@ namespace Mono.Security {
                                return GetASN1 ().GetBytes ();
                        }
                }
+
+               internal class SortedSet : IComparer {
+
+                       public int Compare (object x, object y)
+                       {
+                               if (x == null)
+                                       return (y == null) ? 0 : -1;
+                               else if (y == null)
+                                       return 1;
+
+                               ASN1 xx = x as ASN1;
+                               ASN1 yy = y as ASN1;
+                               
+                               if ((xx == null) || (yy == null)) {
+                                       throw new ArgumentException (Locale.GetText ("Invalid objects."));
+                               }
+
+                               byte[] xb = xx.GetBytes ();
+                               byte[] yb = yy.GetBytes ();
+
+                               for (int i = 0; i < xb.Length; i++) {
+                                       if (i == yb.Length)
+                                               break;
+
+                                       if (xb[i] == yb[i]) 
+                                               continue;
+                                               
+                                       return (xb[i] < yb[i]) ? -1 : 1; 
+                               }
+
+                               // The arrays are equal up to the shortest of them.
+                               if (xb.Length > yb.Length)
+                                       return 1;
+                               else if (xb.Length < yb.Length)
+                                       return -1;
+
+                               return 0;
+                       }
+               }
        }
 }