Author: spouliot
Date: 2007-05-09 12:50:33 -0400 (Wed, 09 May 2007)
New Revision: 77035

Modified:
   trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog
   trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs
Log:
        * PKCS12.cs: Adds SecretBag support. Patch by Jay Miller.


Modified: trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog
===================================================================
--- trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog  2007-05-09 
16:39:34 UTC (rev 77034)
+++ trunk/mcs/class/Mono.Security/Mono.Security.X509/ChangeLog  2007-05-09 
16:50:33 UTC (rev 77035)
@@ -1,5 +1,6 @@
 2007-05-09  Sebastien Pouliot  <[EMAIL PROTECTED]>
 
+       * PKCS12.cs: Adds SecretBag support. Patch by Jay Miller.
        * X509Certificate.cs: Fix IsCurrent (use UTC).
 
 2006-12-14  Sebastien Pouliot  <[EMAIL PROTECTED]>

Modified: trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs
===================================================================
--- trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs  2007-05-09 
16:39:34 UTC (rev 77034)
+++ trunk/mcs/class/Mono.Security/Mono.Security.X509/PKCS12.cs  2007-05-09 
16:50:33 UTC (rev 77035)
@@ -270,8 +270,10 @@
                //private int _version;
                private byte[] _password;
                private ArrayList _keyBags;
+               private ArrayList _secretBags;
                private X509CertificateCollection _certs;
                private bool _keyBagsChanged;
+               private bool _secretBagsChanged;
                private bool _certsChanged;
                private int _iterations;
                private ArrayList _safeBags;
@@ -283,8 +285,10 @@
                {
                        _iterations = recommendedIterationCount;
                        _keyBags = new ArrayList ();
+                       _secretBags = new ArrayList ();
                        _certs = new X509CertificateCollection ();
                        _keyBagsChanged = false;
+                       _secretBagsChanged = false;
                        _certsChanged = false;
                        _safeBags = new ArrayList ();
                }
@@ -505,6 +509,24 @@
                        }
                }
 
+               public ArrayList Secrets {
+                       get {
+                               if (_secretBagsChanged) {
+                                       _secretBags.Clear ();
+                                       foreach (SafeBag sb in _safeBags) {
+                                               if (sb.BagOID.Equals 
(secretBag)) {
+                                                       ASN1 safeBag = sb.ASN1;
+                                                       ASN1 bagValue = safeBag 
[1];
+                                                       byte[] secret = 
bagValue.Value;
+                                                       _secretBags.Add(secret);
+                                               }
+                                       }
+                                       _secretBagsChanged = false;
+                               }
+                               return ArrayList.ReadOnly(_secretBags);
+                       }
+               }
+
                public X509CertificateCollection Certificates {
                        get {
                                if (_certsChanged) {
@@ -741,7 +763,8 @@
                                        // TODO
                                        break;
                                case secretBag: 
-                                       // TODO
+                                       byte[] secret = bagValue.Value;
+                                       _secretBags.Add(secret);
                                        break;
                                case safeContentsBag:
                                        // TODO - ? recurse ?
@@ -936,6 +959,63 @@
                        return safeBag;
                }
 
+               private ASN1 SecretBagSafeBag (byte[] secret, IDictionary 
attributes) 
+               {
+                       ASN1 safeBag = new ASN1 (0x30);
+                       safeBag.Add (ASN1Convert.FromOid (secretBag));
+                       ASN1 bagValue = new ASN1 (0x80, secret);
+                       safeBag.Add (bagValue);
+
+                       if (attributes != null) {
+                               ASN1 bagAttributes = new ASN1 (0x31);
+                               IDictionaryEnumerator de = 
attributes.GetEnumerator ();
+
+                               while (de.MoveNext ()) {
+                                       string oid = (string)de.Key;
+                                       switch (oid) {
+                                       case PKCS9.friendlyName:
+                                               ArrayList names = 
(ArrayList)de.Value;
+                                               if (names.Count > 0) {
+                                                       ASN1 pkcs12Attribute = 
new ASN1 (0x30);
+                                                       pkcs12Attribute.Add 
(ASN1Convert.FromOid (PKCS9.friendlyName));
+                                                       ASN1 attrValues = new 
ASN1 (0x31);
+                                                       foreach (byte[] name in 
names) {
+                                                               ASN1 attrValue 
= new ASN1 (0x1e);
+                                                               attrValue.Value 
= name;
+                                                               attrValues.Add 
(attrValue);
+                                                       }
+                                                       pkcs12Attribute.Add 
(attrValues);
+                                                       bagAttributes.Add 
(pkcs12Attribute);
+                                               }
+                                               break;
+                                       case PKCS9.localKeyId:
+                                               ArrayList keys = 
(ArrayList)de.Value;
+                                               if (keys.Count > 0) {
+                                                       ASN1 pkcs12Attribute = 
new ASN1 (0x30);
+                                                       pkcs12Attribute.Add 
(ASN1Convert.FromOid (PKCS9.localKeyId));
+                                                       ASN1 attrValues = new 
ASN1 (0x31);
+                                                       foreach (byte[] key in 
keys) {
+                                                               ASN1 attrValue 
= new ASN1 (0x04);
+                                                               attrValue.Value 
= key;
+                                                               attrValues.Add 
(attrValue);
+                                                       }
+                                                       pkcs12Attribute.Add 
(attrValues);
+                                                       bagAttributes.Add 
(pkcs12Attribute);
+                                               }
+                                               break;
+                                       default:
+                                               break;
+                                       }
+                               }
+
+                               if (bagAttributes.Count > 0) {
+                                       safeBag.Add (bagAttributes);
+                               }
+                       }
+
+                       return safeBag;
+               }
+
                private ASN1 CertificateSafeBag (X509Certificate x509, 
IDictionary attributes) 
                {
                        ASN1 encapsulatedCertificate = new ASN1 (0x04, 
x509.RawData);
@@ -1014,7 +1094,7 @@
                        return hmac.ComputeHash (data, 0, data.Length);
                }
 
-                /*
+               /*
                 * SafeContents ::= SEQUENCE OF SafeBag
                 * 
                 * SafeBag ::= SEQUENCE {
@@ -1087,36 +1167,8 @@
                                }
 
                                if (certsSafeBag.Count > 0) {
-                                       byte[] certsSalt = new byte [8];
-                                       RNG.GetBytes (certsSalt);
-
-                                       ASN1 seqParams = new ASN1 (0x30);
-                                       seqParams.Add (new ASN1 (0x04, 
certsSalt));
-                                       seqParams.Add (ASN1Convert.FromInt32 
(_iterations));
-
-                                       ASN1 seqPbe = new ASN1 (0x30);
-                                       seqPbe.Add (ASN1Convert.FromOid 
(pbeWithSHAAnd3KeyTripleDESCBC));
-                                       seqPbe.Add (seqParams);
-
-                                       byte[] encrypted = Encrypt 
(pbeWithSHAAnd3KeyTripleDESCBC, certsSalt, _iterations, certsSafeBag.GetBytes 
());
-                                       ASN1 encryptedCerts = new ASN1 (0x80, 
encrypted);
-
-                                       ASN1 seq = new ASN1 (0x30);
-                                       seq.Add (ASN1Convert.FromOid 
(PKCS7.Oid.data));
-                                       seq.Add (seqPbe);
-                                       seq.Add (encryptedCerts);
-
-                                       ASN1 certsVersion = new ASN1 (0x02, new 
byte [1] { 0x00 });
-                                       ASN1 encData = new ASN1 (0x30);
-                                       encData.Add (certsVersion);
-                                       encData.Add (seq);
-
-                                       ASN1 certsContent = new ASN1 (0xA0);
-                                       certsContent.Add (encData);
-
-                                       PKCS7.ContentInfo bag = new 
PKCS7.ContentInfo (PKCS7.Oid.encryptedData);
-                                       bag.Content = certsContent;
-                                       safeBagSequence.Add (bag.ASN1);
+                                       PKCS7.ContentInfo contentInfo = 
EncryptedContentInfo (certsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
+                                       safeBagSequence.Add (contentInfo.ASN1);
                                }
                        }
 
@@ -1138,7 +1190,22 @@
                                }
                        }
 
+                       // Doing SecretBags separately in case we want to 
change their encryption independently.
+                       if (_safeBags.Count > 0) {
+                               ASN1 secretsSafeBag = new ASN1 (0x30);
+                               foreach (SafeBag sb in _safeBags) {
+                                       if (sb.BagOID.Equals (secretBag)) {
+                                               secretsSafeBag.Add (sb.ASN1);
+                                       }
+                               }
 
+                               if (secretsSafeBag.Count > 0) {
+                                       PKCS7.ContentInfo contentInfo = 
EncryptedContentInfo (secretsSafeBag, pbeWithSHAAnd3KeyTripleDESCBC);
+                                       safeBagSequence.Add (contentInfo.ASN1);
+                               }
+                       }
+
+
                        ASN1 encapsulates = new ASN1 (0x04, 
safeBagSequence.GetBytes ());
                        ASN1 ci = new ASN1 (0xA0);
                        ci.Add (encapsulates);
@@ -1177,6 +1244,41 @@
                        return pfx.GetBytes ();
                }
 
+               // Creates an encrypted PKCS#7 ContentInfo with safeBags as its 
SafeContents.  Used in GetBytes(), above.
+               private PKCS7.ContentInfo EncryptedContentInfo(ASN1 safeBags, 
string algorithmOid)
+               {
+                       byte[] salt = new byte [8];
+                       RNG.GetBytes (salt);
+
+                       ASN1 seqParams = new ASN1 (0x30);
+                       seqParams.Add (new ASN1 (0x04, salt));
+                       seqParams.Add (ASN1Convert.FromInt32 (_iterations));
+
+                       ASN1 seqPbe = new ASN1 (0x30);
+                       seqPbe.Add (ASN1Convert.FromOid (algorithmOid));
+                       seqPbe.Add (seqParams);
+
+                       byte[] encrypted = Encrypt (algorithmOid, salt, 
_iterations, safeBags.GetBytes ());
+                       ASN1 encryptedContent = new ASN1 (0x80, encrypted);
+
+                       ASN1 seq = new ASN1 (0x30);
+                       seq.Add (ASN1Convert.FromOid (PKCS7.Oid.data));
+                       seq.Add (seqPbe);
+                       seq.Add (encryptedContent);
+
+                       ASN1 version = new ASN1 (0x02, new byte [1] { 0x00 });
+                       ASN1 encData = new ASN1 (0x30);
+                       encData.Add (version);
+                       encData.Add (seq);
+
+                       ASN1 finalContent = new ASN1 (0xA0);
+                       finalContent.Add (encData);
+
+                       PKCS7.ContentInfo bag = new PKCS7.ContentInfo 
(PKCS7.Oid.encryptedData);
+                       bag.Content = finalContent;
+                       return bag;
+               }
+
                public void AddCertificate (X509Certificate cert)
                {
                        AddCertificate (cert, null);
@@ -1457,7 +1559,57 @@
                        }
                }
 
+               public void AddSecretBag (byte[] secret)
+               {
+                       AddSecretBag (secret, null);
+               }
 
+               public void AddSecretBag (byte[] secret, IDictionary attributes)
+               {
+                       bool found = false;
+
+                       for (int i = 0; !found && i < _safeBags.Count; i++) {
+                               SafeBag sb = (SafeBag)_safeBags [i];
+
+                               if (sb.BagOID.Equals (secretBag)) {
+                                       ASN1 bagValue = sb.ASN1 [1];
+                                       byte[] ssecret = bagValue.Value;
+
+                                       if (Compare (secret, ssecret)) {
+                                               found = true;
+                                       }
+                               }
+                       }
+
+                       if (!found) {
+                               _safeBags.Add (new SafeBag (secretBag, 
SecretBagSafeBag (secret, attributes)));
+                               _secretBagsChanged = true;
+                       }
+               }
+
+               public void RemoveSecretBag (byte[] secret)
+               {
+                       int sIndex = -1;
+
+                       for (int i = 0; sIndex == -1 && i < _safeBags.Count; 
i++) {
+                               SafeBag sb = (SafeBag)_safeBags [i];
+
+                               if (sb.BagOID.Equals (secretBag)) {
+                                       ASN1 bagValue = sb.ASN1 [1];
+                                       byte[] ssecret = bagValue.Value;
+
+                                       if (Compare (secret, ssecret)) {
+                                               sIndex = i;
+                                       }
+                               }
+                       }
+
+                       if (sIndex != -1) {
+                               _safeBags.RemoveAt (sIndex);
+                               _secretBagsChanged = true;
+                       }
+               }
+
                public AsymmetricAlgorithm GetAsymmetricAlgorithm (IDictionary 
attrs)
                {
                        foreach (SafeBag sb in _safeBags) {
@@ -1539,6 +1691,52 @@
                        return null;
                }
 
+               public byte[] GetSecret (IDictionary attrs)
+               {
+                       foreach (SafeBag sb in _safeBags) {
+                               if (sb.BagOID.Equals (secretBag)) {
+                                       ASN1 safeBag = sb.ASN1;
+
+                                       if (safeBag.Count == 3) {
+                                               ASN1 bagAttributes = safeBag 
[2];
+
+                                               int bagAttributesFound = 0;
+                                               for (int i = 0; i < 
bagAttributes.Count; i++) {
+                                                       ASN1 pkcs12Attribute = 
bagAttributes [i];
+                                                       ASN1 attrId = 
pkcs12Attribute [0];
+                                                       string ao = 
ASN1Convert.ToOid (attrId);
+                                                       ArrayList dattrValues = 
(ArrayList)attrs [ao];
+
+                                                       if (dattrValues != 
null) {
+                                                               ASN1 attrValues 
= pkcs12Attribute [1];
+
+                                                               if 
(dattrValues.Count == attrValues.Count) {
+                                                                       int 
attrValuesFound = 0;
+                                                                       for 
(int j = 0; j < attrValues.Count; j++) {
+                                                                               
ASN1 attrValue = attrValues [j];
+                                                                               
byte[] value = (byte[])dattrValues [j];
+                                                                       
+                                                                               
if (Compare (value, attrValue.Value)) {
+                                                                               
        attrValuesFound += 1;
+                                                                               
}
+                                                                       }
+                                                                       if 
(attrValuesFound == attrValues.Count) {
+                                                                               
bagAttributesFound += 1;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                               if (bagAttributesFound == 
bagAttributes.Count) {
+                                                       ASN1 bagValue = safeBag 
[1];
+                                                       return bagValue.Value;
+                                               }
+                                       }
+                               }
+                       }
+
+                       return null;
+               }
+
                public X509Certificate GetCertificate (IDictionary attrs)
                {
                        foreach (SafeBag sb in _safeBags) {

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to